本博文使用简单易懂的方式讲解数据结构,并用C语言进行了实现,即使你是零基础,本博文也会为你铺平学习之路,相信读完本博客你会对数据结构有更深一步的了解和认识。
本博文中提到的所有数据结构都使用C语言进行了实现,限于篇幅原因,博主将所有实现数据结构的代码放在了Github上,读者可自行查阅。
为了避免篇幅过长,本博文中所有数据结构的具体操作细节会在《数据结构》专栏 的具体文章中讲解。每种数据结构下都附有该数据结构详解的链接,以及使用C语言实现的Github地址,希望可以方便大家学习。
目录
先验知识——C语言
为了更好地使用C语言
学习数据结构,本节我们介绍实现数据结构我们应该掌握的一些基础知识。
对于很多C语言基础不够好,又不想再系统地去学习的童鞋,建议一看博主推出的数据结构第一课,相信对C语言基础不够好又想快速学习数据接结构的童鞋大有帮助。
C语言0基础
的童鞋,建议先学习C语言,博主推荐谭浩强的《C语言程序设计
》(博主这里有电子版,给大家上传的时候遇到了问题,有需要的童鞋可以留言或邮件联系,文章结尾有邮箱),不过很多人可能会说这本教程并不是很好,作为0基础的我们而言,学会C语言的一些基本知识已经够了,而且该书作为很多学校的教材,因此可以一读以了解C语言。
当然这里还推荐菜鸟教程,相信过一遍之后相信你会对C语言有一些基本的了解。
链表
链表是一种逻辑上连续,而存储结构上非连续的一种存储结构,即:链表是由一些在存储位置上不连续的数据组成的。因此,链表的每个结点应包含两个部分:一个是数据域,用于存储数据,另一个是指针域,用于存储其相邻结点的地址。
PS: 每个单元都会存储数据,为了把每个存储单元的数据串起来,每个单元会存储相邻单元的地址(指针域的作用)
优点:
- 链表不需要初始化容量,可以任意加减元素;
- 添加或者删除元素时只需要改变前后两个元素结点的指针域的指向地址即可,所以添加,删除很快
缺点:
- 因为含有大量的指针域,占用空间较大
- 查找元素需要遍历链表来查找,非常耗时
适用场景:
- 数据量较小,需要频繁增加,删除操作的场景
单链表
单链表是一种链式存取的数据结构,由每个结点单元连接而成。
每个结点单元由两部分组成:数据域和指针域,其中数据域用来存储数据,指针域用来存储下一结点的地址。
因此,每个结点的结构体可以表示为:
struct node
{
数据域;
struct node *next;//指针域
}
单链表的示意图如下:
为避免博文篇幅过长,博主将单链表的插入、删除、查找、遍历等操作的细节及C语言实现整理到了《数据结构》专栏中,链接如下:
单链表的详解及实现见单链表及C语言实现
单链表所有相关操作实现的代码见Github
双链表
双链表也叫双向链表,如下图所示,不同于单链表,对于任意一个结点,链表是“双向”的:每一个结点都包含指针pre
(用于指向当前结点的直接前驱结点),数据域
(用于存储数据元素)和指针next
(用于指向当前结点的直接后继结点)。
双链表中结点的结构体如下所示:
struct node
{
struct node *pre;
数据域;
struct node *next;
}
为避免博文篇幅过长,博主将双链表的插入、删除、查找、遍历等操作的细节及C语言实现整理到了《数据结构》专栏中,链接如下:
双链表的详解及实现见双链表及C语言实现
双链表所有相关操作实现的代码见Github
循环单链表
单链表中,链表的最后一个结点的指针为NULL
,每次遍历单链表都需要从头结点开始访问。
不同于单链表,循环单链表的示意图如下所示,循环单链表的尾结点的指针不为空,其指向了头结点,这样一来每次遍历单链表就不一定非得从头结点开始,从任意结点都可以遍历整个循环单链表。
循环单链表的结构体和单链表的结构体一样:
struct node
{
数据域;
struct node *next;
}
为避免博文篇幅过长,博主将循环单链表的插入、删除、查找、遍历等操作的细节及C语言实现整理到了《数据结构》专栏中,链接如下:
循环单链表的详解及实现见循环单链表及C语言实现
循环单链表所有相关操作实现的代码见Github
循环双链表
双链表中,每个结点单元都有一个数据域和两个指针域,每个结点的pre
指针指向上一个结点(若为头结点则指向NULL
),每个结点的next
指针指向下一个结点(若为尾节点则指向NULL
)。
循环双链表与双链表大体差不多,只是在头结点和尾节点有所区别:
- 头结点的
pre
指针指向尾结点 - 尾结点的
next
指针指向头结点
因此,循环双链表的任何结点都不包含NULL
循环双链表的示意图如下:
循环双链表的结构体与双链表一样:
struct node
{
struct node *pre;
数据域;
struct node *next;
}
为避免博文篇幅过长,博主将循环双链表的插入、删除、查找、遍历等操作的细节及C语言实现整理到了《数据结构》专栏中,链接如下:
循环双链表的详解及实现见循环双链表及C语言实现
循环双链表所有相关操作实现的代码见Github
小结
对以上链表所有操作做一总结我们可以发现:链表里所有定义的指针都应该被用到(要么指向NULL
,要么指向某一结点),只要记住这一点我们对链表的操作就游刃有余了:
1. 单链表尾结点的next
指向NULL
2. 双链表头结点pre
指向NULL
,尾结点的next
指向NULL
3. 循环单链表尾结点的next
指向head
4. 循环双链表尾结点的next
指向head
,头结点的pre
指向尾结点
堆栈
堆栈,也称为栈,是一种只能在一端(称为栈顶)对数据项进行操作的一种数据结构。
数据的操作有两种:
- 插入,称为入栈
- 删除,称为出栈
堆栈的示意图如下:
由于只能在顶端执行插入和删除,因此最先插入堆栈的元素将最后从堆栈中删除,因此,有时堆栈被称为后进先出(Last In First Out,LIFO)列表。
堆栈的数组实现
为避免博文篇幅过长,博主将堆栈的C语言数组实现的细节及C语言实现整理到了《数据结构》专栏中,链接如下:
堆栈数组实现的详解见堆栈的数组实现(C语言)
堆栈所有相关操作数组实现的代码见Github
堆栈的链表实现
为避免博文篇幅过长,博主将堆栈的C语言链表实现的细节及C语言实现整理到了《数据结构》专栏中,链接如下:
堆栈链表实现的详解见堆栈的链表实现(C语言)
堆栈所有相关操作链表实现的代码见Github
队列
队列是一种允许在一端(队尾,rear)进行插入操作,另一端(队头,front)进行删除操作的数据结构。
- 插入:在队尾进行,也称为入队
- 删除:在队头进行,也称为出队
队列的示意图如下:
队列只能在一端进行插入,另一端进行删除,从示意图可以看出,队列里的元素是按照入队的顺序出队的(因此队列经常被用在排队等候类的应用中)。
根据队列的特征,队列也被称为先进先出(First In First Out,FIFO)列表。
队列的数组实现
为避免博文篇幅过长,博主将队列的C语言数组实现的细节及C语言实现整理到了《数据结构》专栏中,链接如下:
队列数组实现的详解见队列的数组实现(C语言)
队列所有相关操作数组实现的代码见Github
队列的链表实现
为避免博文篇幅过长,博主将队列的C语言链表实现的细节及C语言实现整理到了《数据结构》专栏中,链接如下:
队列链表实现的详解见队列的链表实现(C语言)
队列所有相关操作链表实现的代码见Github
循环队列
循环队列是为了解决数组队列的“假溢出”现象以提高空间利用率而提出的。
为避免博文篇幅过长,博主将队列的C语言链表实现的细节及C语言实现整理到了《数据结构》专栏中,链接如下:
循环队列的详解及实现见循环队列及C语言实现
循环队列所有相关操作实现的代码见Github
树
树是由有限个结点组成的具有层次关系的集合,在逻辑关系上看起来像一颗倒挂的树而得名,包括无序树,有序树,二叉树,哈夫曼树等
二叉树
二叉树是一种树型结构,其特点是每个结点至多有两颗子树,这两颗子树有左右之分,顺序不能颠倒。如图就是一个二叉树的例子:
- 除最后一层外,其他层的结点均有
2
个结点的二叉树称为满二叉树
- 对满二叉树按照从上到下,从左到右的顺序编号,如果有一个二叉树不是满二叉树,该树的编号又与满二叉树的编号对应,则称为
完全二叉树
二叉树的性质
二叉树每个结点至多有两棵子树,因此如果二叉树的每个节点都都包含至多即2
个结点,即满二叉树,则
- 第 i i i层上有 2 i − 1 2^{i-1} 2i−1个结点( i ≥ 1 i\ge1 i≥1)
- 深度为 k k k的二叉树有 2 k − 1 2^{k}-1 2k−1个结点
任何一颗二叉树,如果其终端结点
(没有子树的结点)数为
n
e
n_e
ne,度为2
的结点数为
n
2
n_2
n2,则
- n e = n 2 + 1 n_e=n_2+1 ne=n2+1
具有n
个结点的完全二叉树的深度为
- ⌊ l o g 2 n + 1 ⌋ \lfloor log_2n +1\rfloor ⌊log2n+1⌋
为避免博文篇幅过长,博主将二叉树的操作细节及C语言实现整理到了《数据结构》专栏中,链接如下:
二叉树的详解及实现见二叉树及C语言实现
二叉树所有相关操作实现的代码见Github
二叉搜索树
为避免博文篇幅过长,博主将二叉搜索树的操作细节及C语言实现整理到了《数据结构》专栏中,链接如下:
二叉搜索树的详解及实现见二叉搜索树及C语言实现
二叉搜索树所有相关操作实现的代码见Github
平衡搜索树(AVL)
为避免博文篇幅过长,博主将平衡搜索树的操作细节及C语言实现整理到了《数据结构》专栏中,链接如下:
平衡搜索树(AVL)的详解及实现见平衡搜索树(AVL)及C语言实现
平衡搜索树所有相关操作实现的代码见Github
B树
为避免博文篇幅过长,博主将B树的操作细节及C语言实现整理到了《数据结构》专栏中,链接如下:
B树的详解及实现见B树及C语言实现
B树所有相关操作实现的代码见Github
B+树
为避免博文篇幅过长,博主将B+树的操作细节及C语言实现整理到了《数据结构》专栏中,链接如下:
B+树的详解及实现见及C语言实现
B+树所有相关操作实现的代码见Github
图
广度优先搜索(BFS)
为避免博文篇幅过长,博主将广度优先搜索的操作细节及C语言实现整理到了《数据结构》专栏中,链接如下:
广度优先搜索(BFS)的详解及实现见广度优先搜索(BFS)及C语言实现
BFS所有相关操作实现的代码见Github
深度优先搜索(DFS)
为避免博文篇幅过长,博主将深度优先搜索的操作细节及C语言实现整理到了《数据结构》专栏中,链接如下:
深度优先搜索(DFS)的详解及实现见深度优先搜索(DFS)及C语言实现
DFS所有相关操作实现的代码见Github
生成树
为避免博文篇幅过长,博主将生成树的操作细节及C语言实现整理到了《数据结构》专栏中,链接如下:
生成树的详解及实现见生成树及C语言实现
生成树所有相关操作实现的代码见Github
才疏学浅,难免有错误和不当之处,欢迎交流批评指正!
同时有问题的话欢迎留言或邮箱联系(ljt_IT@163.com)。