链表概述:链表是一种常见的数据结构。数组可以存放数据,但是使用数组时要先指定数组中包含元素的个数,即数组长度。但是如果向这个数组中加入的元素个数超过了数组的大小时,便不能将内容完全保存。例如在定义一个班级的人数时,如果小班是30人,普通班是50人,且定义班级人数时使用数组,那么要定义数组的个数为最大,也就是最少为50个元素,否则不满足最大时的情况。这种方式非常浪费空间。而链表,其存储元素的个数不受限定的,当进行添加元素的时候存储的个数就会随之改变。

如图1所示为链表结构的示意图

在链表中有一个头指针变量,图中head表示的就是头指针,这个指针变量保存一个地址。从图中的箭头可以看到该地址为一个变量的地址,也就是说头指针指向一个变量。这个变量称为元素,在链表中每一个元素包括两个部分:数据部分和指针部分。数据部分用来存放元素所包含的数据,而指针部分用来指向下一个元素。最后一个元素指针指向NULL,表示指向的地址为空。从图1可以看到,head头结点指向第一个元素,第一个元素中的指针又指向第二个元素,第二个元素的指针又指向第三个元素的地址,第三个元素的指针就指向为空。

根据对链表的描述,可以想象到链表就像一个铁链,一环扣一环。然后通过头指针寻找链表中的元素,这就好比在一个幼儿园中,老师拉着第一个小朋友的手,第一个小朋友又拉着第二个小朋友的手,这样下去在幼儿园中的小朋友就连成了一条线。最后一个小朋友没有拉着任何人,他的手是空着的,他就好像是链表中链尾,而老师就是头指针,通过老师就可以找到这个队伍中的任何一个小朋友。

注意:在链表这种结构中,必须利用指针才能实现。因此链表中的结点应该包含一个指针变量来保存下一个结点的地址。

三个函数:

void *malloc(unsigned int size);

该函数的功能是在内存中动态地分配一块size大小的内存空间。malloc函数会返回一个指针,该指针指向分配的内存空间,如果出现错误则返回NULL。

void *calloc(unsigned int n,unsigned int size);

该函数的功能是在内存中动态分配n个长度为size的连续内存空间数组。calloc函数会返回一个指针,该指针指向动态分配的连续内存空间地址。当分配空间错误时,返回NULL。

void free(void *ptr);

该函数的功能是使用由指针ptr指向的内存区,使部分内存区能被其他变量使用(简单来说就是释放不需要的内存空间)。ptr是最近一次调用calloc或malloc函数时返回的值,free函数无返回值。

链表的插入操作:链表的插入操作可以在链表的头指针位置进行(图3),也可以在某个结点的位置进行,或者可以像创建结构时在链表的后面添加结点(图2)。这三种插入操作的思想都是一样的。

链表头插入结点的过程就比如手拉手的小朋友连成一条线,这时又来了一个小朋友他要站在老师和一个小朋友的中间,那么老师就要放开原来的小朋友,拉住新加入的小朋友。这个新加入的小朋友就拉住原来的那个小朋友。这样,这条连成的线还是连在一起。

链表的删除操作:当希望删除链表中的结点时,应该怎么办?还是通过前文中小朋友手拉手的比喻进行理解。例如队伍中的一个小朋友离开队伍了,并且这个队伍不会断开的方法只需他两边的小朋友将手拉起来就可以了。

例如在一个链表中删除其中的一点:

通过图4可以发现要删除一个结点,首先要找到这个结点的位置,例如图中的NO2结点。然后将NO1结点的指针指向NO3结点,最后将NO2结点的内存空间释放掉,这样就完成了结点的删除操作。

实例:

#include

#include

struct student//学生结构体

{

char name[20];//姓名

int number;//学号

struct student * next;//指向下一个结点的指针

};

int count;//全局变量表示链表长度

/*

create函数的功能是创建链表,在create的外部可以看到一个整型的全局变量count,这个变量

的作用是表示链表中结点的数量。在create函数中,首先定义需要用到的指针变量,head用来表示头

指针,end用来指向原来的尾结点,new指向新创建的结点。

使用malloc函数分配内存,先用end和new两个指针都指向第一个分配的内存。然后显示提示信息,

先输入一个学生的姓名,再输入学生的学号。使用while进行判断,如果学号为0,则不执行循环语句。

在while循环中,count++自加操作表示链表中结点的增加。然后要判断新加入的结点是否是第一次

加入的结点,如果是第一次加入结点则执行if语句块中的代码,否则执行else语句块中的代码。

在if语句块中,因为第一次加入结点时其中没有结点,所以新结点即为首结点也为最后一个结点,

并且要将新加入的结点的指针指向NULL,即为head指向。else语句实现的是链表中已经有结点存在时的

操作。首先将新结点new的指针指向NULL,然后将原来最后一个结点的指针指向新结点,最后将end指针

指向最后一个结点。

这样一个结点创建完之后,要再进行分配内存,然后向其中输入数据,通过while语句再次判断输入

的数据是否符合结点的要求。当结点不符合要求时,执行下面的代码,调用free函数将不符合要求的结点

空间进行释放。

*/

struct student * create()

{

struct student * head = NULL;//初始化链表头指针为空

struct student * end,* new;

count = 0;//初始化链表长度

end = new = (struct student *)malloc(sizeof(struct student));

printf("please first enter name,then nember\n");

scanf("%s",new->name);

scanf("%d",&new->number);

while(0 != new->number)

{

count++;

if(1 == count)

{

new->next = head;//使得指向为空

end = new;//跟踪新加入的结点

head = new;//头指针指向首结点

}

else

{

new->next = NULL;//新结点的指针为空

end->next = new;//原来的尾结点指向新结点

end = new;//end指向新结点

}

new = (struct student *)malloc(sizeof(struct student));//再次分配结点内存空间

scanf("%s",new->name);

scanf("%d",&new->number);

}

free(new);//释放没用到的空间

return head;

}

/*

print函数是用来将链表中的数据进行输出。在函数的参数中,head表示一个链表的头结点。

在函数中,定义一个临时的指针temp用来进行循环操作。定义一个整型变量表示链表中的结点序号。

然后将临时指针temp指针变量保存首结点的地址。

使用while语句将所有的结点中保存的数据都显示输出。其中每输出一个结点的内容后,就移动

temp指针变量指向下一个结点的地址。当最后一个结点时,所拥有的指针指向NULL,此时循环结束。

*/

void print(struct student * head)

{

struct student *temp;//循环所用的临时指针

int index = 1;//表示链表中结点的序号

printf("---the list has %d members:---\n\n",count);

temp = head;//指针得到首结点的地址

while(NULL != temp)

{

printf("the NO%d member is:\n",index); //输出结点序号

printf("the name is:%s\n",temp->name);//输出姓名

printf("the number is:%d\n\n",temp->number); //输出学号

temp = temp->next;//移动临时指针到下一个结点

index++;

}

}

/*

insert函数为链表头插入操作函数,在代码中,为要插入的新结点分配内存,然后向新结点中输入数据。这样

一个结点就创建完成了,接下来就是将这个结果插入到链表中。首先将新结点的指针指向原来的首结点,保存首结

点的地址。然后将头指针指向新结点,这样就完成了结点的连接操作,最后增加链表的结点数量。

*/

struct student * insert(struct student * head)

{

struct student * new;//指向新分配的空间

printf("---insert member at first---\n");

new = (struct student *)malloc(sizeof(struct student));//分配内存空间,并返回指向该内存空间的指针

scanf("%s",new->name);

scanf("%d",&new->number);

new->next = head;//新结点指针指向原来的首结点

head = new;//头指针指向新结点

count++;//增加链表结点数量

return head;

}

/*

为delete函数传递两个参数,head表示链表的头指针,index表示要删除结点在链表中的位置。

定义整型变量i用来控制循环的次数,然后定义两个指针,分别用来表示要删除的结点和这个结点

之前的结点。

输出一行提示信息表示要进行删除操作,之后利用for语句进行循环操作找到要删除的结点,

使用temp保存要删除结点的地址,pre保存前一个结点的地址。找到要删除的结点后,连接删除结点

两边的结点,并使用free函数将temp指向的内存空间进行释放。

*/

void delete(struct student * head,int index)//head表示头结点,index表示要删除的结点下标

{

int i;//控制循环变量

struct student * temp;//临时指针

struct student * pre;//表示要删除结点前的结点

temp = head;//得到头结点

pre = temp;

printf("---delete NO%d member---\n\n\n",index);

for(i=1;i

{

pre = temp;

temp = temp->next;

}

pre->next = temp->next;//连接删除结点两边的结点

free(temp);//释放掉要删除结点的内存空间

count--;//减少链表中的元素个数

}

/*

在main函数中,先定义一个头结点指针head,然后调用create函数创建链表,并将链表的头结点

返回给head指针变量。利用得到的头结点head作为print函数的参数。

在main函数中分别添加代码执行插入和删除操作。

*/

int main()

{

struct student * head;//定义头结点

head = create();//创建结点

print(head);//输出链表

head = insert(head);//插入结点

print(head);//输出链表

delete(head,2);//删除第二个结点

print(head);//输出链表

return 0;

}

参考文献:[C语言从入门到精通].王娣等

[C语言从入门到精通].王娣等PDF文档下载地址:

c语言链表中何时用点何时用箭头,链表基本操作及其过程详细叙述相关推荐

  1. c语言找出链表中倒数第k的数,查找链表中倒数第k个结点

    题目:输入一个单向链表,输出该链表中倒数第 k 个结点.链表的倒数第 0 个结点为链表的尾指针. 分析:为了得到倒数第 k 个结点,很自然的想法是先走到链表的尾端,再从尾端回溯 k 步.可是输入的是单 ...

  2. python语言学习:python语言学习中的定义类、定义函数、封装api等详细攻略

    python语言学习:python语言学习中的定义类.定义函数.封装api等详细攻略 目录 python语言学习中的定义类 python语言学习中的定义函数 python语言学习中封装api pyth ...

  3. 一个单向链表,输出该链表中倒数第k个结点,链表的倒数第0个结点为链表的尾指针

    输入一个单向链表,输出该链表中倒数第k个结点.链表的倒数第0个结点为链表的尾指针 typedef struct _node_t {struct _node_t *next;int data; }Nod ...

  4. c语言链表中何时用点何时用箭头,C语言指针五——指针应用:链表

    C语言指针五--指针应用:链表 --从代码猜测作者的意图毕竟是一件痛苦的事,这也是为什么许多人接手别人的项目宁愿从头做起也不愿意使用现有代码的原因. 链表是一种重要的数据结构,它是许多其他数组结构的和 ...

  5. 设某链表中最常用的操作是在链表的尾部_Redis系列(二)底层数据结构之双端链表...

    前言 定义 优劣 双向链表 无环链表 带有头指针和尾指针 带有长度计数器 总结 参考文章 联系我 前言 Redis 已经是大家耳熟能详的东西了,日常工作也都在使用,面试中也是高频的会涉及到,那么我们对 ...

  6. python删除链表中重复的节点_Java编程删除链表中重复的节点问题解决思路及源码分享...

    一. 题目 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 二. 例子 输入链表:1->2->3->3->4->4-&g ...

  7. 剑指offer(C++)-JZ22:链表中倒数最后k个结点(数据结构-链表)

    作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 题目描述: 输入一个长度为 n 的链表,设链表中的元素的值为 ai ,返回该链表中倒数第k个节点 ...

  8. 剑指offer面试题22. 链表中倒数第k个节点(链表)

    题目描述 输入一个链表,输出该链表中倒数第k个节点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点.例如,一个链表有6个节点,从头节点开始,它们的值依次是1.2.3.4.5. ...

  9. 链表相关操作:创建链表、遍历链表、求链表长度、链表中删除一个节点、链表中插入一个节点、反转单链表...

    1 #include<iostream> 2 #include<stdlib.h> 3 4 typedef struct node 5 { 6 int data; 7 stru ...

最新文章

  1. JSP笔记-页面重定向
  2. BiB: 电子科大邹权组构建基于肠道菌群平衡的疾病预测模型及微生物生物标志物发掘平台...
  3. 李刚java视频_《Srping视频教程》疯狂Java 李刚老师[WMV]
  4. (转)ADC的滤波方法
  5. 反素数(luogu 1463)
  6. 电信申请固定ip_各个代理ip之间的关系
  7. zabbix安装步骤
  8. C++ 20 还未发布,就已凉凉?
  9. 为什么mysql查询结果有前缀_字符串的公共前缀对Mysql B+树查询影响回溯分析
  10. 洛谷 P1509 找啊找啊找GF(复习二维费用背包)
  11. uniapp —— 配合腾讯地图实现小程序自动定位
  12. Macbook pro/air 2013 late -2014 使用转接卡更换NVME SSD休眠不醒问题的解决办法
  13. PHP-laravel框架一1
  14. 惠威D1080带来精致听音感受
  15. AMCL中odom的数据处理
  16. CenterNet:Objects as Points代码解析(九):通过高斯函数画热点图
  17. 软件测试岗月薪3w+的测试,到底强在哪里?测试开发真的就是天花板了吗?
  18. Prometheus监控-下
  19. NNDL 实验六 卷积神经网络(3)LeNet实现MNIST
  20. 企业选择SOP作业指导书系统的目的和意义

热门文章

  1. BetaFlight统一硬件配置文件研读之resource命令
  2. 高等数学(一) 微积分研究的主要对象
  3. BIUT比特信任系统公链 双周报 第65期
  4. 【时空融合:遥感图像】
  5. jzoj3290. 【JSOI2013】吃货JYY
  6. Linux下如何打包文件
  7. js前端身份证号、手机号脱敏、手机号、身份证号加密(ios浏览器兼容性问题)
  8. CAD在线转换PDF格式怎么操作?
  9. 音乐怪兽来袭 诺基亚X7港行即将开卖
  10. 时间宝贵,Java 并发编程复习路线。