数据结构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;
}
树的遍历
前序遍历
后序遍历

二叉树

二叉树的实现

二叉查找树

二叉平衡树

其他树

红黑树

图基本概念

图的存储

图的遍历

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

拓扑排序

关键路径

最小生成树

最短路径问题

相关推荐
lapiii3581 小时前
图论-代码随想录刷题记录[JAVA]
java·数据结构·算法·图论
win x3 小时前
链表(Linkedlist)
数据结构·链表
杜若南星3 小时前
保研考研机试攻略(满分篇):第二章——满分之路上(1)
数据结构·c++·经验分享·笔记·考研·算法·贪心算法
曙曙学编程4 小时前
初级数据结构——栈
数据结构
严文文-Chris4 小时前
【B+树特点】
数据结构·b树
严文文-Chris4 小时前
B-树特点以及插入、删除数据过程
数据结构·b树
欧阳枫落4 小时前
python 2小时学会八股文-数据结构
开发语言·数据结构·python
手握风云-4 小时前
零基础Java第十六期:抽象类接口(二)
数据结构·算法
<但凡.5 小时前
编程之路,从0开始:知识补充篇
c语言·数据结构·算法
f狐0狸x6 小时前
【数据结构副本篇】顺序表 链表OJ
c语言·数据结构·算法·链表