[数据结构与算法] 初识八大数据结构

本文参考了
zejian_ 的博文系列:《 java数据结构与算法》
拭心 的博文系列:《Java 集合框架》


数据结构

一、数组(Array)

数组可以存储具有相同数据类型的元素集合,如int,float或者自定义类型等,当我们创建一个数组时,计算机操作系统会为该数组分配一块连续的内存块,这也就意味着数组中的每个存储单元的地址都是连续的,因此只要知道了数组的起始内存地址就可以通过简单的乘法和加法计算出数组中第n-1个存储单元的内存地址,从而获取对应的值。

引申:
线性表是由n(n>=0)个类型相同的数据元素a0,a1,…,an-1组成的有限的序列,在数学中记作(a0,a1,…,an-1),其中ai的数据类型可以是基本数据类型(int,float等)、字符或类。n代表线性表的元素个数,也称其为长度(Length)。若n=0,则为空表;若n > 0,则ai(0 < i < n-1)有且仅有一个前驱(Predecessor)元素ai-1和一个后继(Successor)元素ai+1,a0没有前驱元素,ai没有后继元素。

线性表的顺序存储设计与实现(顺序表)(数组)
线性表的链式存储设计与实现(链表)


二、栈(Stack)

栈是一种用于存储数据的简单数据结构,有点类似链表或者顺序表(统称线性表)。栈与线性表的最大区别是数据的存取的操作,我们可以这样认为栈(Stack)是一种特殊的线性表。其插入和删除操作只允许在线性表的一端进行,一般而言,把允许操作的一端称为栈顶(Top),不可操作的一端称为栈底(Bottom),同时把插入元素的操作称为入栈(Push),删除元素的操作称为出栈(Pop),栈的特点就是后进先出LIFO(Last In First Out)。若栈中没有任何元素,则称为空栈 。


三、队列(Queue)

队列同样是一种特殊的线性表,其插入和删除的操作分别在表的两端进行,队列的特点就是先进先出FIFO(First In First Out)。我们把向队列中插入元素的过程称为入队(Enqueue),删除元素的过程称为出队(Dequeue)并把允许入队的一端称为队尾,允许出的的一端称为队头,没有任何元素的队列则称为空队。


四、链表(Linked List)

线性链表的存储结构是用若干个地址分散的存储单元存放数据元素的,逻辑上相邻的数据元素在物理位置上不一定相邻,因此每个存储单元中都会有一个地址指向域,这个地址指向域指明其后继元素的位置。在链表中存储数据的单元称为结点(Node),一个结点至少包含了数据域和地址域,其中数据域用于存储数据,而地址域用于存储前驱或后继元素的地址。链表的插入和删除都相当便捷,这是由于链表中的结点的存储空间是在插入或者删除过程中动态申请和释放的,不需要预先给单链表分配存储空间的,从而避免了顺序表因存储空间不足需要扩充空间和复制元素的过程,提高了运行效率和存储空间的利用率。


五、树(Tree)

强烈推荐博客:https://blog.csdn.net/javazejian/article/details/53727333

树是数据元素之间具有次层关系的非线性的结构,树是由n(n≥0)个结点组成的有限集合,n=0的树是空树,n大于0的树T由以下两个条件约定构成:

  • 有一个特殊的结点,称为根结点(root),它没有前驱结点只有后继结点。
  • 除了根结点之外的其他结点分为m(0≤m≤n)个互不相交的集合T0,T1,T2,…,Tm−1,其中每个集合Ti也是一个树型结构,称之为子树(Subtree)。
    图片
    专业术语:
    (1)根结点: 根结点是没有双亲的结点,一棵树中最多有一个根结点(如上图的A结点)。
    (2)孩子结点:一棵树中,一个结点的子树的根结点称为其孩子结点,如上图的A的孩子结点右B、C、D。
    (3)父母结点:相对于孩子结点而已其前驱结点即为父母结点,如上图的B、C、D 三个结点的父母结点都为A,当然E、F结点的父母结点则是B。
    (4)兄弟结点:拥有相同的父母结点的所有孩子结点叫作兄弟结点,如上图B、C、D 三个结点共同父结点为A,因此它们是兄弟结点,E、F也是兄弟结点,但是F、G就肯定不是兄弟结点了。
    (5)祖先结点:如果存在一条从根结点到结点Q的路径,而且结点P出现在这条路径上,那么P就是Q的祖先结点,而结点Q也称为P的子孙结点或者后代。如上图的E的祖先结点有A和B,而E则是A和B的子孙结点。
    (6)叶子结点:没有孩子结点的结点叫作叶子结点,如E、F、G、H等。
    (7)结点的度:指的是结点所拥有子树的棵数。如A的度为3,F的度为0,即叶子结点的度为0,而树的度则是树中各个结点度的最大值,如图(d)树的度为3(A结点)
    (8)树的层:又称结点的层,该属性反映结点处于树中的层次位置,我们约定根结点的层为1,如上图所示,A层为1,B层为2,E的层为3。
    (9)树的高度(深度):是指树中结点的最大层数,图(d)的高度为3。
    (10)边:边表示从父母结点到孩子结点的链接线,如上图(d)中A到B间的连线则称为边。

1. 二叉树

定义:

二叉树(Binary Tree)是n(n≥0)个结点组成的有限集合,n=0时称为空二叉树;n>0的二叉树由一个根结点和两棵互不相交、分别称为左子树和右子树的子二叉树构成。二叉树也是递归定义的,上节定义的度、层次等术语,同样适用于二叉树。

性质:

  • 二叉树第i层最多有2i-1(i≥1) 个结点。如第4层,最多有23=8个节点。
  • 在高度为h的二叉树中,最多有2h−1个结点(h≥0)。(为满二叉树)
1.1 满二叉树

一棵高度为h的满二叉树(Full Binary Tree)是具有2h−1(h≥0)个结点的二叉树。
最大特点是每一层次的结点数都达到最大值

1.2 完全二叉树

对于完全二叉树,假设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。

在这里插入图片描述
二叉树存储结构:链式存储结构 + 顺序存储结构(仅适用于完全二叉树或满二叉树)

  1. 链式存储结构:主要有二叉链表和三叉链表两种
    二叉链表结构主要由一个数据域和两个分别指向左、右孩子的结点组成,其结构如下:
BinaryNode(T data , BinaryNode<T> left , BinaryNode<T> right )

在这里插入图片描述
采用二叉链表存储结构,每个结点只存储了到其孩子结点的单向关系,而没有存储到父结点的关系,这样的话,每次要获取父结点时将消耗较多的时间,因为需要从root根结点开始查找,花费的时间是遍历部分二叉树的时间,而且与该结点的位置有关。为了更高效的获取父结点,三叉链表存储结构孕育而生了。

三叉链表存储结构
三叉链表主要是在二叉链表的基础上多添加了一个指向父结点的域,这样我们就存储了父结点与孩子结点的双向关系,当然这样也增加了一定的空开销其结点结构如下:

ThreeNode(T data ,ThreeNode<T> parent,ThreeNode<T> left,ThreeNode<T> right)

在这里插入图片描述

1.3 二叉查找树

二叉查找树的特性是,对于树中的每个结点T(T可能是父结点),它的左子树中所有项的值小T中的值,而它的右子树中所有项的值都大于T中的值。这意味着该树所有的元素可以用某种规则进行排序(取决于Comparable接口的实现)。

二叉树的遍历规则主要有四种:先根次序遍历,中根次序遍历,后根次序遍历以及层次遍历。

1.3.1 先根次序遍历

访问规则是先遍历根结点,再遍历左子树,最后遍历右子树。如下图遍历的次序为ABEFC

在这里插入图片描述

1.3.2 中根次序遍历

访问规则是先遍历左子树,再遍历根结点,最后遍历右子树。如下图遍历的次序为EBFACH

在这里插入图片描述

1.3.3 后根次序遍历

访问规则是先访问左子树,再访问右子树,最后访问根结点。如下图遍历的次序为EFBHCA

在这里插入图片描述

1.3.4 层次遍历

访问规则是特性就是兄弟优先访问,两个兄弟结点的访问顺序是先左后右的。同样它们的后代结点的访问次序也是先左后右,左兄弟的所有孩子结点一定优先右兄弟的孩子访问。如下图遍历的次序为ABCDEHG

在这里插入图片描述

2. 红黑树

3. B+树


六、散列表(Hash)

散列表,也叫哈希表,是根据关键码和值 (key和value) 直接进行访问的数据结构,通过key和value来映射到集合中的一个位置,这样就可以很快找到集合中的对应元素。

记录的存储位置=f(key)

这里的对应关系 f 成为散列函数,又称为哈希 (hash函数),而散列表就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里,这种存储空间可以充分利用数组的查找优势来查找元素,所以查找的速度很快。

哈希表在应用中也是比较常见的,就如Java中有些集合类就是借鉴了哈希原理构造的,例如HashMap,HashTable等,利用hash表的优势,对于集合的查找元素时非常方便的,然而,因为哈希表是基于数组衍生的数据结构,在添加删除元素方面是比较慢的,所以很多时候需要用到一种数组链表来做,也就是拉链法。拉链法是数组结合链表的一种结构,较早前的hashMap底层的存储就是采用这种结构,直到jdk1.8之后才换成了数组加红黑树的结构,其示例图如下:

在这里插入图片描述
从图中可以看出,左边很明显是个数组,数组的每个成员包括一个指针,指向一个链表的头,当然这个链表可能为空,也可能元素很多。我们根据元素的一些特征把元素分配到不同的链表中去,也是根据这些特征,找到正确的链表,再从链表中找出这个元素。

哈希表的应用场景很多,当然也有很多问题要考虑,比如哈希冲突的问题,如果处理的不好会浪费大量的时间,导致应用崩溃。


七、堆(Heap)


八、图


算法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值