数据结构教程(详细又简单——C语言实现)

本博文使用简单易懂的方式讲解数据结构,并用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)。

循环双链表与双链表大体差不多,只是在头结点和尾节点有所区别:

  1. 头结点的pre指针指向尾结点
  2. 尾结点的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指向尾结点

堆栈

堆栈,也称为栈,是一种只能在一端(称为栈顶)对数据项进行操作的一种数据结构。

数据的操作有两种:

  1. 插入,称为入栈
  2. 删除,称为出栈

堆栈的示意图如下:
在这里插入图片描述
由于只能在顶端执行插入和删除,因此最先插入堆栈的元素将最后从堆栈中删除,因此,有时堆栈被称为后进先出(Last In First OutLIFO)列表。

堆栈的数组实现

为避免博文篇幅过长,博主将堆栈的C语言数组实现的细节及C语言实现整理到了数据结构》专栏中,链接如下:

堆栈数组实现的详解见堆栈的数组实现(C语言)

堆栈所有相关操作数组实现的代码见Github

堆栈的链表实现

为避免博文篇幅过长,博主将堆栈的C语言链表实现的细节及C语言实现整理到了数据结构》专栏中,链接如下:

堆栈链表实现的详解见堆栈的链表实现(C语言)

堆栈所有相关操作链表实现的代码见Github

队列

队列是一种允许在一端(队尾,rear)进行插入操作,另一端(队头,front)进行删除操作的数据结构。

  1. 插入:在队尾进行,也称为入队
  2. 删除:在队头进行,也称为出队

队列的示意图如下:
在这里插入图片描述

队列只能在一端进行插入,另一端进行删除,从示意图可以看出,队列里的元素是按照入队的顺序出队的(因此队列经常被用在排队等候类的应用中)。

根据队列的特征,队列也被称为先进先出(First In First OutFIFO)列表。

队列的数组实现

为避免博文篇幅过长,博主将队列的C语言数组实现的细节及C语言实现整理到了数据结构》专栏中,链接如下:

队列数组实现的详解见队列的数组实现(C语言)

队列所有相关操作数组实现的代码见Github

队列的链表实现

为避免博文篇幅过长,博主将队列的C语言链表实现的细节及C语言实现整理到了数据结构》专栏中,链接如下:

队列链表实现的详解见队列的链表实现(C语言)

队列所有相关操作链表实现的代码见Github

循环队列

循环队列是为了解决数组队列的“假溢出”现象以提高空间利用率而提出的。

为避免博文篇幅过长,博主将队列的C语言链表实现的细节及C语言实现整理到了数据结构》专栏中,链接如下:

循环队列的详解及实现见循环队列及C语言实现

循环队列所有相关操作实现的代码见Github

树是由有限个结点组成的具有层次关系的集合,在逻辑关系上看起来像一颗倒挂的树而得名,包括无序树,有序树,二叉树,哈夫曼树等

二叉树

二叉树是一种树型结构,其特点是每个结点至多有两颗子树,这两颗子树有左右之分,顺序不能颠倒。如图就是一个二叉树的例子:
在这里插入图片描述

  • 除最后一层外,其他层的结点均有2个结点的二叉树称为满二叉树
  • 对满二叉树按照从上到下,从左到右的顺序编号,如果有一个二叉树不是满二叉树,该树的编号又与满二叉树的编号对应,则称为完全二叉树

二叉树的性质

二叉树每个结点至多有两棵子树,因此如果二叉树的每个节点都都包含至多2个结点,即满二叉树,则

  • i i i层上有 2 i − 1 2^{i-1} 2i1个结点( i ≥ 1 i\ge1 i1
  • 深度为 k k k的二叉树有 2 k − 1 2^{k}-1 2k1个结点

任何一颗二叉树,如果其终端结点(没有子树的结点)数为 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)。

创作不易,觉得写得不错就微信扫码奖励一下吧!

Reward

数据结构——用C语言描述(第3版)》课后答案的描述使用C语言实现各种数据结构和算法。以下是对几个常见数据结构的描述和相关代码示例。 1. 数组(Array):数组是一种线性数据结构,用于存储相同类型的元素。C语言中使用数组可以快速访问和修改元素。示例代码如下: ```c #include <stdio.h> int main() { int arr[5] = {1, 2, 3, 4, 5}; for(int i = 0; i < 5; i++) { printf("%d ", arr[i]); } return 0; } ``` 2. 链表(Linked List):链表是一种动态数据结构,通过节点之间的指针链接来存储数据。C语言中可以使用结构体和指针来实现链表。示例代码如下: ```c #include <stdio.h> #include <stdlib.h> struct Node { int data; struct Node* next; }; void printList(struct Node* head) { struct Node* current = head; while(current != NULL) { printf("%d ", current->data); current = current->next; } } int main() { struct Node* head = NULL; struct Node* second = NULL; struct Node* third = NULL; head = (struct Node*) malloc(sizeof(struct Node)); second = (struct Node*) malloc(sizeof(struct Node)); third = (struct Node*) malloc(sizeof(struct Node)); head->data = 1; head->next = second; second->data = 2; second->next = third; third->data = 3; third->next = NULL; printList(head); return 0; } ``` 3. (Stack):是一种后进先出(LIFO)的数据结构,在C语言中可以使用数组来实现。示例代码如下: ```c #include <stdio.h> #define MAX_SIZE 100 int stack[MAX_SIZE]; int top = -1; void push(int item) { if(top == MAX_SIZE - 1) { printf("Stack Overflow\n"); } else { stack[++top] = item; } } int pop() { if(top == -1) { printf("Stack Underflow\n"); return -1; } else { return stack[top--]; } } void printStack() { for(int i = top; i >= 0; i--) { printf("%d ", stack[i]); } } int main() { push(1); push(2); push(3); printf("Popped element: %d\n", pop()); printStack(); return 0; } ``` 这些示例代码展示了如何使用C语言描述《数据结构——用C语言描述(第3版)》中介绍的数据结构。读者可以根据书中提供的习题进行编程练习,进一步巩固数据结构和算法的相关知识。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值