数据结构Java实现

#1024程序员节 | 征文#

线性结构

最基本、最简单、最常用的一种数据结构------线性表。线性表分为一般线性表和受限线性表。

一般线性表:通常所说的线性表,可以自由地删除或添加节点。

受限线性表:节点操作受限制的线性表,如栈和队列。

线性表是n个数据元素的有限序列。线性表中的数据元素要求具有相同类型。

线性表特征

1.有且仅有一个开始节点(表头节点),它没有直接前驱,只有一个直接后继。

2.有且仅有一个终端节点(表尾节点),它没有直接后继,只有一个直接前驱。

3.其他节点都有一个直接前驱和直接后继。

4.元素之间为一对一的线性关系。

  • 数据类型:数据类型是指在编程语言中定义的一种数据的分类,指定数据的大小、取值范围、所允许的操作等。常见的数据类型包括整型、浮点型、字符型、布尔型等。
  • 抽象数据类型(ADT):抽象数据类型是对数据及其操作的一种抽象描述,它定义了一组数据和对这些数据的操作,但不关心具体的实现细节。ADT强调"是什么"而非"怎么做",例如栈、队列、图等。

示例:

  • 数据类型 :例如,intfloatchar等。
  • 抽象数据类型:例如,栈(Stack)可以定义两种基本操作:入栈(push)和出栈(pop),而不关心其内部是如何用数组、链表等结构实现的。

顺序表/数组

顺序表是指用一组**++地址连续++** 的存储单元依次存储数据元素的线性表。数组 是计算机根据事先定义好的数组类型与长度自动为其分配的一组**++连续的存储单元++**,相同数组的位置和距离都是固定的,任何一个数组元素的地址都可用简单公式计算。因此这种结构可以有效地对数组元素进行随机访问。

表的简单数组实现:对表的所有操作都可以通过数组实现。虽然数组可以动态指定,但是还是需要对表大小进行估计。查找容易(索引),然而插入和删除需要的运行时间多得多,因为增删位置后面的数据都要向前或向后移动。

ArrayList的实现:ArrayList是一种++线性数据结构,底层用数组实现的++ ,与简单数组实现方式不同,它的**++容量能动态增长++**。

ArrayList特点

链表

顺序表进行数组元素插入删除时,会引起大量数据移动,复杂低效。链表应运而生。

链表是一种++物理存储单元非连续,非顺序++ 的++存储结构++ ,数据元素的逻辑顺序是通过链表中的**++指针链接++**次序实现的。

链表由一系列节点 (链表中的每一个元素称为一个节点)组成,节点可以在运行时动态生成。每个节点包括两部分:++存储数据元素的数据域 ,指向下一个指针的指针域++。指针域记录了下一个节点的地址。

使用链表克服了顺序表要预先知道数据大小的缺点。链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。插入删除方便,元素无需大量移动; 查找不方便

Java没有显式的使用指针

单向链表

大佬文章 Java实现单链表(步骤详解+源码)_java单链表-CSDN博客

单向链表的节点结构

java 复制代码
public class Node {
    private T data;
    private Main.Node next=null;

    private Node (T data){
        this.data=data;
    }

    //获得某节点下一个节点
    public Main.Node getNext(){
        return next;
    }

    //获得某节点存储的数据
    public T getData(){
        return data;
    }
}

链表的删除

寻找特定节点的前驱节点

链表的插入

测试链表是否为空表

当前链表是否为最后一个节点

查找指定元素的节点,返回找到的第一个节点,未找到返回null

获取链表下一个节点

++上面的回来再补++

双向链表

双向链表在单向链表数据结构上附加了一个域,使它包含指向前一个节点的指针。它的开销增加了一个附加的链,增加了对空间的需求,同时也使插入和删除的运行时间增加了一倍。在**++插入删除++** 时的操作和原来的单链表有不同,这次需要**++修改两个方向上的指针++**。

JDK对双向链表节点的定义

java 复制代码
    private static class Node<E>{
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next){
            this.item=element;
            this.next=next;
            this.prev=prev;
        }
    }

删除节点

插入节点

++回头写++

循环链表

让最后一个节点反过来指向第一个节点,整个链表形成一个环。

链表应用:例如实现一元多项式及其运算

哈希表

查找方法

顺序表的查找
  • 从顺序表的第一个元素开始,逐个与要查找的关键字比较。
  • 如果找到与关键字相等的元素,则返回该元素在顺序表中的位置。
  • 如果遍历完整个顺序表都没有找到与关键字相等的元素,则返回一个表示未找到的标志,通常为0或-1。
java 复制代码
int Search_Sequen(SSTable ST, KeyType key) {
	// 在线性表 ST 中顺序检索其关键字等于Key的数据元素,
	// 若找到,函数值为该元素在表中的位置,否则为 -1.
	ST.element[ST.length].key=key; //设置监视哨
	i=0;
	while (ST.element[i].key != key) i++;
	if (i < ST.length)
      	return i;
	else
		return -1;
}
有序表的查找

折半查找

java 复制代码
int BinarySearch(int a[],int x,int n){
    int left = 0;
    int right = n-1;
 
    while(left <= right){
    
    int mid=(left+right)/2;
 
    if(x==a[middle])
        return middle;
    if(x>a[middle])
        left=middle+1;
    else
        right=middle-1;
    }
    return -1;
}
索引顺序表的查找

又叫++分块查找++

分块查找,又称‌索引顺序查找,是顺序查找法与二分法的一种结合‌。其基本思想是将线性表分成若干块,每一块中的结点存放不必有序,但块与块之间必须有序。

  1. ‌、查找过程 ‌:
    • 首先对索引表进行二分查找或顺序查找,以确定待查记录在哪一块中。
    • 然后在已确定的块中用顺序法进行查找。
散列表的查找

散列,又称哈希,是一种重要的存储方法,也是一种常见的查找方法。

基本思想:以元素的关键字key为自变量,通过一个确定的函数关系h,计算出对应的函数值h(key),把这个值解释为元素的存储地址,并按此存放;查找时,由同一个函数对给定值kx计算地址,将kx与地址单元中元素关键字进行比较,确定查找是否成功。因此散列法又称为关键字-地址转换法 。其中转换函数称为++散列函数++ ,这个思想构造的表称为++散列表++。

当两个关键字散列到同一个值,称为冲突

常见散列函数

1.直接定址法:简单但适用范围有限‌

2.数字分析法:选取关键码中分布均匀的几位作为散列地址。这种方法适用于关键码的某些位上符号分布均匀的情况‌。

3.平方取中法:通过取关键字的平方值的中间若干位作为散列值。这种方法较少使用,因为其计算复杂度较高‌。

4.折叠法:当关键码位数较多时,将关键码分割成若干部分,然后将这些部分叠加起来形成散列地址‌。

5.除留余数法:将关键字除以一个数取余数作为散列值,例如H(key) = key % mod。这种方法适用于关键字分布均匀的情况,特别是当mod为素数时‌。

如何解决冲突

拉链法
开放定址法

不建立链表,仍设散列表的长度为M,地址范围为[0,M-1]。从空表开始,通过逐个向表中插入新元素来建立散列表。

插入关键字值为key的新元素的方法 是:从h(key)开始,按照某种规定的次序探查允许插入新元素的空位置。地址h(key)为基位置。如果h(key)已经被占用了,那么就需要有一种解决冲突的策略来确定如何探查下一个空位置。所以这种方法也称为++空缺编址法++。

根据生成探查序列的规则不同,有++线性探查法、伪随机探查法、平方探查法和双散列探查法++等开发定址法。

再散列法

++装填因子α=填入表中的元素个数/散列表的长度++

所以α越大,填入表的元素越多,产生冲入的可能性越大。

队列

限定在表的一端插入,在表的另一端删除的线性表。

FIFO:先进先出。

队列ADT

add:向队列中加入一个新元素

remove:从队列首部移除一个元素

peek:返回队首元素,而不将其移除

队列的顺序/数组实现

假溢出👇

可能出现++假溢出++ ,改进方法:++循环队列++。

循环队列

队头指针进1:head=(head+1)%MaxQueueSize

队尾指针进1:tail=(tail+1)%MaxQueueSize

在循环队列结构下,当head=tail为空队列;当(tail+1)%MaxQueueSize=head为满队列。

👇

队列的链接表示

head和tail分别指向队头和队尾节点。

限定插入和删除都在同一端进行的线性表。

LIFO:后进先出。

栈ADT

Stack:建栈

push:入栈

pop:出栈

peek:返回栈顶元素

empty:判断是否是空栈

search:查找元素在栈的位置

栈有++顺序和链接++两种表达方式。

大佬文章 数据结构------栈_栈分为哪两种-CSDN博客

栈的顺序表示

顺序栈的函数实现

++回头写++

栈的链接表示

栈顶指针指向栈顶元素

链式栈的函数实现

++回头写++

常见应用场景:表达式计算

计算后缀表达式的值

中缀表达式转换为后缀表达式

利用两个栈计算表达式

递归和栈的关系

大佬文章 理解递归的本质:递归与栈_栈与递归-CSDN博客

矩阵(百度说是线性结构)

稀疏矩阵:数值为0的元素数目远多于非零元素数目

稠密矩阵:非零元素数目多

特殊矩阵:上三角/下三角/对角矩阵

对称矩阵关于主对角线对称,只需存储上/下三角即可。

三角矩阵:下图c为一个常数

带状矩阵

大佬文章 数组与矩阵-CSDN博客

矩阵的压缩存储 :大佬文章 矩阵的压缩存储-CSDN博客

三元组表示 :大佬文章稀疏矩阵的三元组表表示法及其转置_三元组稀疏矩阵转置-CSDN博客

十字链表 :大佬文章稀疏矩阵的链式存储结构:十字链表-CSDN博客

排序

冒泡、选择、插入、希尔

Java 排序算法-CSDN博客

非线性结构

(优先队列)

树基础知识

树的实现
java 复制代码
public class MyTree1 {
    class TreeNode {
        Object value;
        TreeNode firstChild;//第一个儿子节点
        TreeNode nextSibling;//第一个兄弟节点
    }
    //根节点
    TreeNode root;
    //树节点数目
    int size=0;
}
树的遍历
前序遍历
后序遍历

二叉树

二叉树的实现

二叉查找树

二叉平衡树

其他树

红黑树

图基本概念

图的存储

图的遍历

广度优先遍历
深度优先遍历

拓扑排序

关键路径

最小生成树

最短路径问题

相关推荐
驭渊的小故事7 小时前
简单模板笔记
数据结构·笔记·算法
VT.馒头7 小时前
【力扣】2727. 判断对象是否为空
javascript·数据结构·算法·leetcode·职场和发展
历程里程碑9 小时前
Linux 库
java·linux·运维·服务器·数据结构·c++·算法
Sheep Shaun9 小时前
如何让一个进程诞生、工作、终止并等待回收?——探索Linux进程控制与Shell的诞生
linux·服务器·数据结构·c++·算法·shell·进程控制
Pluchon9 小时前
硅基计划4.0 简单模拟实现AVL树&红黑树
java·数据结构·算法
小龙报9 小时前
【51单片机】从 0 到 1 玩转 51 蜂鸣器:分清有源无源,轻松驱动它奏响新年旋律
c语言·数据结构·c++·stm32·单片机·嵌入式硬件·51单片机
dllxhcjla9 小时前
数据结构和算法
数据结构
历程里程碑11 小时前
普通数组----轮转数组
java·数据结构·c++·算法·spring·leetcode·eclipse
sin_hielo11 小时前
leetcode 1653
数据结构·算法·leetcode
李日灐11 小时前
C++进阶必备:红黑树从 0 到 1: 手撕底层,带你搞懂平衡二叉树的平衡逻辑与黑高检验
开发语言·数据结构·c++·后端·面试·红黑树·自平衡二叉搜索树