【数据结构基础笔记】【链表】

代码参考《妙趣横生的算法.C语言实现》

文章目录

  • 前言
    • 1、链表基础
    • 2、创建一个链表
    • 3、插入结点
    • 4、删除结点
    • 5、销毁链表
    • 6、实例分析


前言

本章总结:链表的定义、创建、销毁,结点的插入与删除


1、链表基础

链表的物理存储结构是用一组地址任意的存储单元存储数据的。
在链表结构中,每个数据元素记录都存放在链表的一个结点node中,而每个结点之间由指针将其连接到一起。
每个结点由指针域(存放后继结点的位置)、数据域构成。
一个链表通常有一个表头,是一个指针变量,用来存放第一个结点地址。
链表的最后一个结点的的指针域要置空,表示为链表的尾结点。
在这里插入图片描述
链表特点:
1、每个结点包括两个部分:数据域和指针域
数据域用来存放数据元素本身信息,指针域用来存放后继结点的地址
2、链表逻辑上是连续的,但物理上不一定是连续存储结点。
3、只要获取链表的头结点,就可以通过指针遍历整条链表
一个链表结点可以描述为:

typedef struct node{ElemType data;		//数据域struct node *next;	//指针域
}LNode,*LinkList;

每个结点的类型是LNode
*LinkList是指向LNode类型数据的指针类型定义。
所以 LNode *L 与 LinkList L; 是等价的。

2、创建一个链表

LinkList GreatLinkList(int n)
{//建立一个长度为n的链表LinkList p,r,list=NULL;		//p:相当于每次新建结点的暂存器,r:相当于插入结点的上一个结点,永远指向原先链表的最后一个结点。list链表的头指针ElemType elem;				//获取暂存数据int i;						//定义累加器for(i=0;i<n;i++){scanf("%d",&elem);p=(LinkList)malloc(sizeof(LNode));	//分配内存,并将首地址送到pp->data=elem;			//置入数据p->next =NULL;			//指针指向NULL,暂时不考虑下一个结点if(!list)				//如果链表为空,则新创建的结点就是该链表的第一个结点list=p;else					//如果链表不为空,则将新建立的结点连接到之前链表的尾部r->next=p;r=p;					//将p结点的数据赋给r}return list;				//将链表的头指针返回主调函数,通过list就可以访问链表中的每个结点,并进行操作	
}

3、插入结点

步骤描述:
1、创建新节点,用指针p指向该结点
2、将q指向结点的next域的值赋值给p指向结点的next域
3、将p的值赋值给q的next域
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ynbLqOhX-1600526323871)(C:\Users\15409\AppData\Roaming\Typora\typora-user-images\1600507457502.png)]
代码描述:

void insertList(LinkList *list,LinkList q,ElemType e)
{//向链表中由指针q指向的结点后面插入结点,结点数据位eLinkList p;p=(LinkList)malloc(sizeof(LNode));		//生成一个新节点,由p指向它p->data=e;if(!*list)				//如果链表为空{*list=p;p->next=NULL;}						//当链表为空的时候,q没有意义,只能在头结点后面插入第一个元素else{//当链表不为空的时候,认为q指向的结点一定存在//将q指向的结点的next域的值赋给p指向的结点的next域p->next=q->next;q->next=p; }
}

通过这个算法同样可以创建一个链表,因为链表为空时,list==NULL,可以自动创建一个结点。在下面创建其他结点时,只要始终将指针q指向链表的最后一个结点,就可以创建出一个链表

4、删除结点

从非空链表中删除q所指的结点。
考虑三个情况:1、q指向的是链表的第一个结点
2、q指向的结点的前驱结点的指针已知
3、q指向的结点的前驱结点的指针未知
步骤:
1:将q所指的结点的指针域next的值赋给头指针list,让list指向第二个结点,再释放掉q所指的结点即可。
2:假设前驱指针为r,将q所指的结点的指针域next的值赋给r的指针域next,释放掉q所指结点
3:当q所指的结点的前驱结点的指针未知,需要通过链表头指针list遍历链表,找到q的前驱结点,并将该指针赋值给变量r,再按照第二种情况去做即可

情况1、2的代码描述:

void delLink(LinkList *list,LinkList r,LinkList q)
{if(q==*list)		//情况1:q指向链表的第一个结点*list=q->next;else				//情况2:q指向的结点前驱结点的指针已知r->next=q->next;free(q);
}

情况1、3的代码描述:

void delLink(LinkList *list,LinkList r,LinkList q)
{if(q==*list)//情况1:q指向链表的第一个结点{*list=q->next;  free(q);}else				//情况3:q指向的结点前驱结点的指针未知{for(r=*list;r->next!=q;r=r->next);	//遍历链表,找到q的前驱结点的指针if(r->next!=NULL){r->next=q->next;			//从链表中删除q指向的结点free(q);}} 
}

5、销毁链表

使用链表之后需要销毁它,因为链表本身会占用内存。
code描述:

void destroyLinkList(LinkList *list)
{LinkList p,q;p=*list;while(p){q=p->next;free(p);p=q;}*list=NULL;
}

6、实例分析

要求:
输入一组整数(大于10个数),以0作为结束标志,将这组整数存放到一个链表中(结束标志0不包括在内),打印出该链表中的值。然后删除该链表中的第5个元素,打印出删除后的结果。最后在内存中释放掉该链表。

#include "stdio.h"
#include "malloc.h"
#include "conio.h"typedef int ElemType;
//指针定义
typedef struct node {ElemType data;		//数据域struct node* next;	//指针域
}LNode, * LinkList;//***********创建链表******************//
//
LinkList GreatLinkList(int n)
{//建立一个长度为n的链表LinkList p, r=NULL, list = NULL;		//p:相当于每次新建结点的暂存器,r:相当于插入结点的上一个结点,永远指向原先链表的最后一个结点。list链表的头指针ElemType elem;				//获取暂存数据int i;						//定义累加器for (i = 0;i < n;i++){scanf("%d", &elem);p = (LinkList)malloc(sizeof(LNode));	//分配内存,并将首地址送到pp->data = elem;			//置入数据p->next = NULL;			//指针指向NULL,暂时不考虑下一个结点if (!list)				//如果链表为空,则新创建的结点就是该链表的第一个结点list = p;else					//如果链表不为空,则将新建立的结点连接到之前链表的尾部r->next = p;r = p;					//将p结点的数据赋给r}return list;				//将链表的头指针返回主调函数,通过list就可以访问链表中的每个结点,并进行操作	
}//*************插入结点************//
//
void insertList(LinkList* list, LinkList q, ElemType e)
{//向链表中由指针q指向的结点后面插入结点,结点数据位eLinkList p;p = (LinkList)malloc(sizeof(LNode));		//生成一个新节点,由p指向它p->data = e;if (!*list)				//如果链表为空{*list = p;p->next = NULL;}						//当链表为空的时候,q没有意义,只能在头结点后面插入第一个元素else{//当链表不为空的时候,认为q指向的结点一定存在//将q指向的结点的next域的值赋给p指向的结点的next域p->next = q->next;q->next = p;}
}
//通过这个算法同样可以创建一个链表,因为链表为空时,list==NULL,可以自动创建一个结点。在下面创建其他结点时,只要始终将指针q指向链表的最后一个结点,就可以创建出一个链表//删除结点
void delLink(LinkList* list, LinkList q)
{LinkList r;if (q == *list)//情况1:q指向链表的第一个结点{*list = q->next;free(q);}else				//情况3:q指向的结点前驱结点的指针未知{for (r = *list;r->next != q;r = r->next);	//遍历链表,找到q的前驱结点的指针if (r->next != NULL){r->next = q->next;			//从链表中删除q指向的结点free(q);}}
}//销毁链表
void destroyLinkList(LinkList* list)
{LinkList p, q;p = *list;while (p){q = p->next;free(p);p = q;}*list = NULL;
}void print_linklist(LinkList show_list)
{while (show_list){printf("%d ",show_list->data);show_list = show_list->next;}
}
int main()
{int elem = 0;   //定义中间变量数据int i = 0;      //定义累加器LinkList L, q;  q = L = GreatLinkList(1);       //创建1个链表结点,q和L指向该结点scanf("%d",&elem);while (elem)                    //循环地输入数据,同时插入新生成的结点,结束条件:输入数据为0{insertList(&L,q,elem);q = q->next;scanf("%d", &elem);}q = L;printf("The content of the linklist\n");print_linklist(q);q = L;printf("\n Delete the fifth element\n");for (i=0;i<4;i++)           //将指针q指向第五个元素{if (q == NULL)     //确保此时链表的长度大于等于5,否则是非法操作{printf("The length of the linklist is smaller than 5");_getche();return 0;}q = q->next;}delLink(&L,q);q = L;print_linklist(q);destroyLinkList(&L);return 0;
}

result:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/378230.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动态添加,删除行之心理测试系统

动态添加&#xff0c;删除行之考试系统 数据库设计&#xff1a; xl_option 题目选项 20090105134755404(编号) 20090105134904421(外键) 比较符合(选项内容) ②(选项标号) 2&#xff08;选项分值&#xff09; xl_subject 题目信息 20090105134943608&#xff08;编号&#xff…

android bitmap裁剪中间,Android裁剪中心位图

虽然上面的大多数答案提供了一种方法来实现这一点&#xff0c;但已经有一种内置的方法来实现这一点&#xff0c;它是一行代码(ThumbnailUtils.extractThumbnail())int dimension getSquareCropDimensionForBitmap(bitmap);bitmap ThumbnailUtils.extractThumbnail(bitmap, di…

二、request请求库

一、requests介绍与安装 1&#xff0c;requests介绍 答&#xff1a;requests是一个优雅且简单的Python HTTP请求库 2&#xff0c;requests作用 答&#xff1a;requests的作用是发送请求获取响应数据 3&#xff0c;requests安装 答&#xff1a;pip install requests 二、…

Java Vector Capacity()方法与示例

向量类的Capacity()方法 (Vector Class capacity() method) capacity() method is available in java.util package. Capacity()方法在java.util包中可用。 capacity() method is used to return the current capacity (i.e. initially, how many object exists) of this Vecto…

MFC和GTK的区别

关键技术 http://blog.csdn.net/master_max/article/details/1540204 MFC和GTK的区别&#xff1f;&#xff1f; 1.  两者都是基于面向对象设计的。尽管MFC是用C写的&#xff0c;而GTK是用C写的&#xff0c;但思想都是面向对象的。GTK使用glib的对象机制&#xff0c;由于用C写…

视频图像质量评价

目录1、人眼视觉特性1、眼的适应性2、对比灵敏度3、空间分辨率和时间分辨率4、马赫效应5、可见度阈值2、图像质量测度3、图像评价方法4、图像评价方法的优劣1、人眼视觉特性 1、眼的适应性 暗适应性&#xff1a;从亮环境到暗环境&#xff0c;适应暗环境的特性 亮适应性&#…

鸿蒙科技与文化,数字阅读 | “华为鸿蒙”:当现代科技遇到古典文化

华为事件愈演愈烈。海思芯片 20 年 " 备胎 " 终转正&#xff0c;那么操作系统呢&#xff1f;最近&#xff0c;华为为自主研发的操作系统注册商标—— " 鸿蒙 "&#xff0c;引发了关于华为注册整本《山海经》的热烈讨论&#xff0c;很多人的朋友圈&#xff…

三、Beautiful Soup解析库

一、Beautiful Soup介绍与安装 1&#xff0c;Beautiful Soup介绍 答&#xff1a;Beautiful Soup是一个可以从HTML或XML文件中提取数据的Python库 2&#xff0c;Beautiful Soup安装 答&#xff1a;安装Beautiful Soup 4&#xff1a;pip install bs4 安装lxml&#xff1a;pip…

strictmath_Java StrictMath sqrt()方法与示例

strictmathStrictMath类sqrt()方法 (StrictMath Class sqrt() method) sqrt() Method is available in java.lang package. sqrt()方法在java.lang包中可用。 sqrt() Method is used to find the square root of the given parameter in the method. Here, "sqrt" st…

recovery编译问题汇总

1、修改支持USB大容量存储 &#xff08;1&#xff09;、首先需要查看手机lun位置 手机链接电脑&#xff0c;打开cmd命令行&#xff0c;依次输入以下命令: adb shell find /sys -name "lun" 输出以下结果&#xff1a; 发现手机输出结果有两个&#xff0c;需要进一步查…

言语理解每日学习及精解20110831

【例题】天气预报一般要考虑气温、气压、温度、风力等因素&#xff0c;这些都是大气层本身变化的结果&#xff0c;只要掌握这些因素&#xff0c;通过计算机的计算就能准确地预报天气变化的趋势。沙尘暴作为一种特殊的天气现象&#xff0c;同样要考虑上述气象因素。据气象学家分…

【数据结构基础笔记】【栈】

代码参考《妙趣横生的算法.C语言实现》 文章目录前言1、栈的定义2、创建一个栈3、入栈和出栈操作4、栈的清空、销毁、计算栈的当前容量5、实例分析前言 本章总结&#xff1a;栈的定义、创建栈&#xff0c;销毁栈&#xff0c;入栈出栈操作等操作。 1、栈的定义 栈是一种重要的…

四、正则表达式

一、正则表达式的概念和作用 正则表达式概念&#xff1a;一种字符串匹配的模式 正则表达式作用&#xff1a; 可以检查一个字符串中是否包含某种字串替换匹配的字串提取某个字符串中匹配的字串 二、正则表达式中常见的语法 字符描述原样字符匹配字符一般字符匹配自身beyondb…

用HTML语言制作list标记,html5 datalist标签的用法是什么?这里有datalist标签的用法实例...

本篇文章主要为大家讲述了关于html5 datalist标签的用法及html5 datalist标签的用法实例。本文说了两个常用的选项框的实例供大家选择观看&#xff0c;下面就让我们一起来看这篇文章吧我们先来看看html5 datalist标签的用法&#xff1a;标签定义选项列表。请与input元素配合使用…

java treemap_Java TreeMap lastKey()方法与示例

java treemapTreeMap类lastKey()方法 (TreeMap Class lastKey() method) lastKey() method is available in java.util package. lastKey()方法在java.util包中可用。 lastKey() method is used to return the last highest key element value exists in this TreeMap. lastKey…

网上看来的

http://blog.163.com/dong_xiao_yang/blog/static/216138205201321114659430/ http://ffmpeg.org/trac/ffmpeg/wiki/How%20to%20compile%20FFmpeg%20for%20Raspberry%20Pi%20%28Raspbian%29#FFmpegwithlibaacpluslibx264andalsa-lib 编译环境 Ubuntu 12.04 w64-mingw32下载lib…

阅读iPhone.3D.Programming(O'Reilly.2010-05) 英文版 第一感觉

最近开始阅读iPhone.3D.Programming(OReilly.2010-05)&#xff0c;英文版此书&#xff0c;我阅读到P21了&#xff0c;中间讲了一个样例&#xff0c;HelloArrow在这个过程中&#xff0c;我想简单点&#xff0c;少打点字&#xff0c;直接拿书中配套来学习&#xff0c;发现一个问题…

【数据结构基础笔记】【队列】

代码参考《妙趣横生的算法.C语言实现》 文章目录前言1、队列定义2、创建一个队列3、入队列4、出队列5、销毁一个队列6、循环队列的概念7、循环队列的实现8、实例分析前言 本章总结&#xff1a;链队列定义&#xff0c;创建&#xff0c;出队入队操作&#xff0c;销毁操作&#x…

html图片自动循环轮播图,js实现图片无缝循环轮播

本文实例为大家分享了js实现图片无缝循环轮播的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下代码如下Document#container{overflow:hidden;width:400px;height:300px;margin:auto;}#front,#container{display:flex;flex-direction:row;}#container img{width:400px…

五、json模块

一、json模块的介绍 json模块是Python自带的模块&#xff0c;用于json和Python数据之间的相互转换 Json与Python数据类型的对应关系 JsonPythonobjectdictarrayliststringstrnumber(int)int,longnumber(real)floattrueTruefalseFalsenullNone [#中括号括起来的&#xff0c;对…