数据结构————链表及其简单应用
来源:互联网 发布:淘宝自动发卡平台 编辑:程序博客网 时间:2024/05/20 23:04
链表及其简单应用1
1.链表的基本概念
- 链表是什么:
链表是一种逻辑顺序是连续的但物理存储单元上非连续、非顺序的存储结构。 - 链表实现方法:
链表是通过以结构体为节点,然后将所有节点通过结构体的指针域指向下一个节点连接起来(连接的实现),将数据存储到数据域中(存储的实现)。
struct node//节点 { int data;//数据域 (数据域可以多组数据,多种类型) struct lianbiao *next;//指针; };
- 链表的优缺点(同数组相比):
优点:不需要预先知道数据的个数,删除添加只需要改变附近节点的指针域
缺点:创建使用麻烦 - 链表的图示:
说明:- 头指针为与链表节点类型相同的指针
- 一般情况情况下,头指针所指向的第一个节点不存数据,这样对在后面进行添加删除排序有很大的便利
- 最后一个节点指针域存NULL。方便在遍历链表时提示遍历完成
2.链表的建立
1.尾插法
- 特点:
输入顺序和存储顺序相同(同头插法相比) - 思路:
- \将新建的节点同之前已连接好的链表最后的节点连接起来,后
- 循环重复步骤1,直到符合终止条件停止循环。
- 使最后一个节点指针域为NULL
- 核心代码:
pEnd->next=pNew;//将新节点同之前已链接好的尾节点链接起来 pEnd=pNew;//尾节指针移动指向新的尾节点 pNew->next=NULL;//结束循环后使尾节点指针域为NULL
- 完整代码:
struct node *create() { int i; struct node *pHead,*pNew,*pEnd; printf("请输入正整数,输入小于0的数停止输入:\n"); pHead=pEnd=(struct node *)malloc(sizeof(struct node));//头指针所指的节点不存数据 pHead->next=NULL; pNew=(struct node *)malloc(sizeof(struct node));//申请新节点 scanf("%d",&pNew->date);//向数据域输入数据 while(pNew->date>0) { pEnd->next=pNew;//连接 pNew->next=NULL;//新节点指针域变空 pEnd=pNew; pNew=(struct node *)malloc(sizeof(struct node)); scanf("%d",&pNew->date); } free(pNew);//释放最后存入小于0的节点 return pHead;//返回头指针 }
- 图示:
画图示意输入 3 4 -1的过程
- 解释:
- pHead,pNew,pEnd 全部为指针变量,类型为结构体,不是结构体变量。
- pHead为头指针,pNew为新建的节点,pEnd为已连接好的节点最后一个节点
2. 头插法
- 特点:
存储顺序与输入顺序相反。 - 思路:
- 将新建节点插入到头结点(不存数据的节点)之后。
- 循环重复步骤1,直到遇到终止条件停止循环
- 核心代码:
pNew->next=pHead->next;//将新节点与第二个连接
pHead->next=pNew;//将新节点与头节点连接 - 完整代码:
struct node *create() { int i; struct node *pHead,*pNew,*pEnd; printf("请输入正整数,输入小于0的数停止输入:\n"); pHead=pEnd=(struct node *)malloc(sizeof(struct node));//头指针所指的节点不存数据 pHead->next=NULL; pNew=(struct node *)malloc(sizeof(struct node));//申请新节点 scanf("%d",&pNew->date);//向数据域输入数据 while(pNew->date>0) { pNew->next=pHead->next;//将新节点与第二个连接 pHead->next=pNew;//将新节点与头节点连接 pNew=(struct node *)malloc(sizeof(struct node)); scanf("%d",&pNew->date); } free(pNew);//释放最后存入小于0的节点 return pHead;//返回头指针 }
- 图示:
此处应该有图,但画图太心累。大家自己动手画吧。●v●
3.链表的遍历以及增删改查
1.遍历链表
- 思路:
- 定义一个指针,初始化为头指针的指针域(不存数据时)
- 访问操作它所指向的节点的数据域
- 移动指针使它指向下一个节点。
- 循环重复1-3,直到指针指向NULL(指针移动到尾节点)
5.遍历是链表操作的基础
- 核心代码:
while(pt!=NULL) { pt=pt->next; }
- 完整代码:
void output(struct node *pHead) { struct node *pt=pHead->next; while(pt!=NULL) { printf("%d\n",pt->date);//输出 pt=pt->next;//指针移动 } }
2.增加新节点
- 思路:
- 新建节点。
- 再利用指针遍历链表找到插入位置的前一个节点(pt),
- 操作指针,插入新建的节点
- 核心代码:
pNew->next=pt->next; pHead->nt=pNew;
- 完整代码:
void increase(struct node *pHead) { struct node *pt=pHead,*pNew; int a; printf("你想插在数字几的后面:\n"); scanf("%d",&a); while(pt&&pt->date!=a) pt=pt->next; if(pt==NULL) printf("未找到这个数\n"); else { pNew=(struct node *)malloc(sizeof(struct node)); printf("输入需要插入的数"); scanf("%d",&pNew->date); pNew->next=pt->next; pt->next=pNew; } }
3. 删除节点
- 思路:
- 寻找需删除的节点和前一个节点
- 操作指针,连接删除节点的前后节点
- 释放需删除节点所占用的内存空间
- 核心代码:
pt_1->next=pt->next;
- 完整代码:
void strike_out(struct node *pHead)//删除 { int a; struct node *pt_1=pHead,*pt=pHead; printf("请输入你想删除数字\n"); scanf("%d",&a); while(pt&&pt->date!=a) { pt_1=pt;//该节点的前一个节点 pt=pt->next; } if(pt==NULL) printf("未找到这个数!\n"); else { pt_1->next=pt->next;//删除 free(pt);//释放空间 printf("已删除!\n"); } }
4.修改数据
- 思路:遍历链表,找到需改变的节点,操作数据域。
- 其他类似与遍历链表
5. 查找数据
- 思路:遍历链表,找到查询的节点,输出数据域。
- 其他类似与遍历链表。
4.升序合并,冒泡排序,插入排序
1. 升序合并
- 思路:
- 建立两个链表,a链和b链
- 定义三个链表指针变量,a,b,c
- a遍历a链,b遍历b链,c用来合并
- 比较a和b当前指的节点。
- c和两者中小的连接起来,移动c和两者中小的指针。循环重复,直到某条链表移动到尾部。将c和未遍历完连接起来。
- 核心代码:
c->next=a(b);//c连接值较小的节点 c=a(b);//c移动 a(b)=a(b)->next;//指向小的节点的指针移动
- 完整代码:
- 想看代码点我
- 或者点我
2. 冒泡排序
- 思路:
- 假设有n个节点。进行n趟排序,每趟比较0到第n-i-1个数(i为趟数)中相邻的节点(使用指针遍历)。
- 符合条件交换节点位置(也可以交换数据)。
- 然后移动指针,注意如果使用交换节点的方法进行冒泡时,有没有交换移动指针的方式不同。
- 核心代码:
交换两个相邻节点(pj和pj_h,pj_1为pj的前一个节点,pt为临时指针) pt=pj->next; pj->next=pj_h->next; pj_h->next=pt; pt=pj_1->next; pj_1->next=pj_h->next; pj_h->next=pt;
- 完整代码:
void sore(struct node *pHead) //排序 { int i,j,flag; struct node *pj_1,*pj,*pj_h,*pt; for(i=0;i<iCound-1;i++) for(j=0,pj=pHead,flag=0;j<iCound-i-1;j++) { if(flag==0) { pj_1=pj; pj=pj->next; pj_h=pj->next; } if(flag==1) { pj_1=pj_1->next; pj_h=pj->next; } flag=0; if((pj->aver)<(pj_h->aver)) { pt=pj->next; pj->next=pj_h->next; pj_h->next=pt; pt=pj_1->next; pj_1->next=pj_h->next; pj_h->next=pt; flag=1; } } }
3. 插入排序
- 思路:
- 将无序节点插入到有序节点。
- 有序表节点初始为第一个节点。
- 将有序表的下一个节点(无序节点的第一个)按大小插入到有序表表中。
- 插入时,先删除需插入的节点(但不释放内存)。再插入。
- 核心代码:
pi_1->next=pi->next;//删除 pi->next=pj->next;//连接 pj->next=pi;
- 完整代码:
void sore(struct node *pHead) //排序 { struct node *pt,*pt_h,*pi; pt=pHead->next; pt_h=pt->next; pHead->next=NULL; while(pt){ for(pi=pHead;pi->next&&pi->next->expn<pt->expn;pi=pi->next); pt_h=pt->next; pt->next=pi->next; pi->next=pt; pt=pt_h; }}
5.简单应用
1.删除a链中与b链重复的节点
- 思路:
- 将a链每一个节点同b链进行比较。(两重循环)
- 删除相同节点
- 完整代码:
- 想看代码点我
- 或者点我
2. n个小孩报m个数的问题
- 问题:n个小孩从1到m报数,报到m的小孩出队,然后继续从0到m报数,报到m的小孩出队。当最后一个报完后,从第1个小孩继续报数,循环重复,直到只剩一名小孩,输出该小孩的序号。
- 思路:
- 建立一个n个节点的循环链表(头结点也存数据,尾节点指针域存头结点地址)。
- 遍历,删除报到第m个数节点。
- 完整代码:
- 想看源代码点我
- 或者点我
3.简单的学生管理习统
- 实现功能:
- 简单的文字界面
- 简单的密码登陆(密码输入的时候显示*)。
- 信息的增删改查
- 按平均分排序。
- 完整代码
- 想看源代码点我
- 或者点我
最后一些废话
写这个博客真很心累,特别是画图,强迫症的我为了对齐,画了好长时间,原计划要画好多图的,因为链表这一块画图真的很有助于理解。非常建议大家画图。最后,我也是初学者,有些地方难免有所疏漏,希望大家可以多多包涵。在评论中指出错误指出。
还有文中的超链接 一份是有道云笔记,一份是我的cmdn代码片。应该都可以直接运行。有什么错误也可以指出。
0 0
- 数据结构————链表及其简单应用
- 数据结构————链表及其简单应用2
- 常用数据结构——队列及其应用
- 常用数据结构——栈及其应用
- 数据结构与算法学习笔记——堆栈及其应用(10以内简单四则计算器)
- 数据结构学习——Huffman树及其应用
- 数据结构学习笔记——栈及其应用
- 数据结构(java)——栈及其应用
- 数据结构—堆排序及其应用(优先级队列)
- 数据结构与算法专题之线性表——栈及其应用
- 数据结构与算法专题之线性表——队列及其应用
- 怎样对10亿个数字快速去重?——浅析位图数据结构及其应用
- 简单数据结构—队列
- 数据结构算法——单链表及其操作
- 数据结构——矩阵及其常用操作
- 数据结构与算法—常用数据结构及其Java实现
- 数据结构实践——顺序表应用
- 数据结构实践——顺序表应用
- Java并发编程系列(一)——Volatile
- 通过 nginx 搞了一个反代,整合 谷歌学术, V2EX ,知乎等搜索的页面
- BZOJ 2152 聪聪可可
- 手机访问电脑中部署的tomcat应用
- 实现算法导论第三版中的二叉搜索树
- 数据结构————链表及其简单应用
- java读取配置文件
- 虚幻UE4中Matinee基础:骨架网格教程
- 基于高度的纹理混合shader
- 东南大学 崇志宏:信息融合和安全综述
- amchart-条形统计图
- 为什么要坚持每天写学到的知识
- 【算法】程序猿不写代码是不对的51
- POJ 1071 Illusive Chase 笔记