数据结构基础三-----之模块一《离散存储【链表】》
来源:互联网 发布:股票涨跌原理 知乎 编辑:程序博客网 时间:2024/06/05 10:23
离散存储【链表】
1.定义:
n个结点离散分配彼此通过指针相连
每个结点只有一个前驱结点,每个结点只有一个后续结点
首结点没有前驱结点,尾结点没有后续结点
2.专业术语:
首结点:第一个存放有效数据的结点
尾结点:最有一个存放有效数据的结点
头结点:头结点的数据类型和首结点的类型是一样的
首结点之前的结点// 第一个有效结点之前的那个指针
头结点并不存放有效数据,也没有存放整个链表中 结点的个数。
加头结点的目的是为了方便对链表的操作
头指针:指向头结点的指针变量 链表的首位置
尾指针:指向尾结点的指针变量
示例1:如何定义一个结点(每一个结点的类型如何表示)
typedef struct Node{ int data; //数据域 struct Node * pNext; //指针域//指针存储的地址只能是 struct Node 类型。//指针域指向的 是与 本身结点数据类型相同的下一个结点 所以数据类型是 struct Node *;}NODE,*PNODE;//NODE 等价于 struct Node,//PNODE 等价于 struct Node *;
3.如果希望一个函数来对链表进行处理,我们至少需要接受链表的哪些信息:
只需要一个参数:头指针以为我们通过头指针可以推算出链表的其他所有参数
4.分类:
单链表:每个结点的指针域只指向后面的结点双链表:每一个结点有两个指针(指前指后)
循环链表:能通过任何一个结点找到其他所有的结点
非循环链表
5.算法:
遍历查找
清空
销毁
求长度
排序
删除结点
插入结点
插入结点:(伪算法)
//第1种写法 r = p->pNext; p->pNext = q; q->pNext = r;//第2种写法 q->pNext = p->pNext; p->pNext = q;//(这两行代码不能倒过来)/* q 本身就是结点的地址 q 指向的就是 结点 q-> pNext 表示的就是结点的指针域 至于指针域中存放的下一个结点的地址是谁 稍加判断就好了。 最重要的!p->pNext //p所指向的结构体变量中 pNext 成员本身。*/
删除结点:(伪算法)
r = p->pNext; p->pNext = p->pNext->pNext; free(r);//这里很重要 一定要记得释放内存,防止内存 溢出
示例2:创建并遍历一个链表,实现判断是否为空,求链表的长度查找删除
仿JAVA中LinkedList对象部分功能的实现
#include<stdio.h>#include<malloc.h>#include<stdlib.h>typedef struct Node{//数据域int data;//指针域struct Node * pNext;//指针域指向的 是与 本身结点数据类型相同的下一个结点 所以数据类型是 struct Node *;}NODE,*PNODE;//NODE 等价于 struct Node,//PNODE 等价于 struct Node *;//函数声明PNODE create_list(void);void traverse_list(PNODE pHead);bool is_empty(PNODE pHead);int length_list(PNODE);bool insert_list(PNODE,int,int);bool delete_list(PNODE,int,int *);void sort_list(PNODE);int main(void){ PNODE pHead = NULL;//等价于 struct Node * pHead = NULL; //create_list()的功能:创建一个非循环单链表,并将该链表的头结点的地址赋给 pHead pHead = create_list(); traverse_list(pHead);//遍历 if(is_empty(pHead)) printf("链表为空\n"); else printf("链表不空\n"); int len = length_list(pHead); printf("链表的长度是%d \n",len); sort_list(pHead); traverse_list(pHead);//遍历 insert_list(pHead,2,33); traverse_list(pHead);//遍历 int val; if(delete_list(pHead,4,&val)) { printf("您删除的元素是%d\n",val); } else { printf("删除失败%d\n",val); } return 0;}//创建一个链表,创建一个非循环单链表,并将该链表的头结点的地址赋给 pHeadPNODE create_list(void){ //C语言里的写法是把所有的变量都定义在前面 int len;//用来存放有效结点的个数 int i; int val;//用来存放用户输入的有效结点的值 //升成一个头结点 头结点的数据类型与 其他结点是相同的。 //分配了一个不存放有效数据的头结点 PNODE pHead = (PNODE)malloc(sizeof(NODE)); if(NULL == pHead) { printf("分配失败,程序终止。\n"); exit(-1); } //pTail 永远指向 尾结点 PNODE pTail = pHead; pTail -> pNext = NULL; printf("请输入您需要生成的链表的结点的个数:len ="); scanf("%d",&len); for(i =0;i<len;++i) { printf("请输入第%d个结点的值:",i+1); scanf("%d",&val); PNODE pNew = (PNODE)malloc(sizeof(NODE)); if(NULL == pNew) { printf("分配失败,程序终止。\n"); exit(-1); } pNew ->data = val; //新生成的结点要挂到整个链表的最后的一个位置。 pTail -> pNext = pNew; pNew ->pNext = NULL; pTail = pNew; } return pHead;}//遍历这个链表void traverse_list(PNODE pHead){//p 指向的是链表的第一个有效结点 PNODE p = pHead->pNext; while(p!= NULL) { printf(" %d",p->data); p = p->pNext; } printf("\n"); return;}//判断链表是否为空bool is_empty(PNODE pHead){ if(pHead->pNext == NULL) return true; else return false;}//返回链表长度int length_list(PNODE pHead){ PNODE p = pHead -> pNext; int len = 0; while(p != NULL) { len++; p = p->pNext; } return len;}//链表排序void sort_list(PNODE pHead){ //实际上算法都是类似 //数组和链表同样都是 线性结构 int i,j,t; PNODE p, q; int len = length_list(pHead); //i 是数组中第一个有效元素的下标 p 是链表中第一个有效元素的 地址。 for(i = 0,p = pHead ->pNext;i<len - 1;++i,p = p->pNext) { // q 就应该是p 的下一个元素 for(j = i+1,q = p ->pNext;j<len;++j,q = q->pNext) {/*请参照数组中的方式来理解 链表if(a[i] > a[j]){ t = a[i]; a[i] = a[j]; a[j] = t;}*/if((p->data )> (q->data)){ t = p->data; p->data = q->data; q->data= t;} } }return;}//在pHead 所指向链表的第pos 个结点的前面插入一个新的结点,该结点的值是 val并且 pos 的值是从1 开始。bool insert_list(PNODE pHead,int pos,int val){ int i = 0; PNODE p = pHead; while(p != NULL && i<pos -1) { p = p->pNext; i++; } if(i>pos-1||p== NULL) return false; PNODE pNew = (PNODE)malloc(sizeof(PNODE)); if(pNew == NULL) { printf("动态分配内存失败"); exit(-1); } pNew ->data = val; //定义了一个临时结点 PNODE q = p->pNext; p->pNext = pNew; pNew ->pNext = q; return true;}//删除指定位置的元素,并用*pVal记录被删除的元素bool delete_list(PNODE pHead,int pos,int * pVal){ int i = 0; PNODE p = pHead; while(p ->pNext!= NULL && i<pos -1) { p = p->pNext; i++; } if(i>pos-1||p ->pNext== NULL) return false; PNODE q = p ->pNext; *pVal = q ->pNext; //删除p结点后面的结点 p->pNext = p->pNext->pNext; free(q); q = NULL; return true;}
阅读全文
0 0
- 数据结构基础三-----之模块一《离散存储【链表】》
- 数据结构基础二-----之模块一《线性存储【数组】》
- 三.学习数据结构之链表(离散存储)
- 数据结构线性结构之离散存储--链表
- 数据结构学习笔记之线性结构--离散存储[链表]
- 数据结构之线性结构的离散存储(单链表)
- 线性表之离散存储(链表)
- 线性表之离散存储(链表)
- 08-数据结构_线性结构-离散存储-链表_1
- 存储管理之离散存储
- C++存储数据结构之三vector
- C++存储数据结构之三vector
- C++存储数据结构之三vector
- 数据结构基础之图的存储结构
- 离散存储---链表
- 离散存储_链表
- python基础系列(三)之高级数据结构
- 数据结构之二叉树基础三
- window下go开发环境的搭建
- DrawerLayout和NavigationView轻松实现抽屉侧滑
- Android Wi-Fi 信号强度--SIGNAL_POLL
- Python3 基本数据类型
- 工厂方法模式(Factory Method Pattern)。
- 数据结构基础三-----之模块一《离散存储【链表】》
- mysql 学习笔记1-基本命令
- 面试题60:把二叉树打印成多行
- jQuery基础笔记_17-07-14
- 2017.07.16 流水帐系列
- swing 画平滑曲线
- 【Unity3D开发】DOTween 插件仿写
- 翻译:kivy语言
- Windows下Python安装与使用