链表——动态存储分配的数据结构
来源:互联网 发布:宜家衣柜 知乎 编辑:程序博客网 时间:2024/06/06 19:57
链表——链式存储结构
① 静态链表:把线性表的元素存放在数组中,这些元素之间通过逻辑关系来连接。数组单元存放链表结点,结点的链域指向下一个元素的位置,即下一个元素所在的数组单元的下标。但是涉及长度定义的问题,所以就出现了动态链表。
② 动态链表:在程序执行过程中从无到有建立起来,一个一个地开辟结点和输入各结点的数据,并建立前后相连的关系。
单链表——所有结点都是单线联系
① 特点:(1)头指针变量存放第一个结点的地址。
(2)每个结点包含一个数据(用户需要的实际数据)和一个指针(存放下一个结点的地址)。
(3)表尾结点不再指向其他结点,指针域为NULL,表示链表到此结束。
② 优点:(1)链表中各结点之间的顺序关系由指针域来确定,不需要占用一片连续的内存空间。
(2)链表可以无限延长(仅受内存总量的限制)。
(3)在插入和删除操作中,只需修改相关结点指针域的链接关系。
即:用则申请,不用则释放,大大提高内存利用率和时间效率。
③ 缺点: 查找元素的速度不如数组。
————————————————————————————————————————————————————————————————————
❤单链表的建立
结点的数据类型必须选用结构体类型,可以包含多个各种类型的成员,而且其中必须含有一个指向本结构体类型的指针成员。以班级学生为例,将学生作为结点,把所有学生的信息存放到链表结构中。首先,要创建结点结构,表示每一个学生。
struct student //学生结构体{ char name[20]; //姓名 int id; //学号 struct student *next; //指向下一个结点的指针};
然后,定义一个create函数,用来创建链表,该函数返回链表的头指针。
int count; //全局变量 表示链表长度struct student *create(){ struct student *head=NULL; //初始化头指针为空 struct student *end,*new; end=new=(struct student *)malloc(sizeof(struct student)); count=0; //初始化链表长度 printf("请输入学生的姓名和学号:\n"); scanf("%s",new->name); scanf("%d",&new->id); while(new->id!=0) //当学生学号不为0,执行循环 { count++; if(count==1) //链表中只有一个结点 { new->next=NULL; //新结点的指向为空 end=new; head=new; //新结点既是首结点又是尾结点 } else //链表中结点个数>1 { new->next=NULL; //新结点的指向为空 end->next=new; //原来的尾结点指向新结点 end=new; //新结点当作尾结点 } new=(struct student *)malloc(sizeof(struct student)); //再次分配结点的内存空间 scanf("%s",new->name); scanf("%d",&new->id); } free(new); //释放结点空间 return head;}
然后用malloc函数分配内存,先将end,new均指向第一个分配的内存,然后输入学生信息。
再使用while语句进行判断,如果学号为0,则结束输入。否则执行循环,继而count自增,表示链表中结点个数的增加,然后判断结点个数。若count==1,进入if语句,因为第一次加入结点,所以新结点new既是首结点,又是尾结点,并且新结点的指针应指向NULL。若count>1,进入else语句,实现的是链表中已经有结点时的插入操作,所以新结点的指针指向NULL,原来的结点指向新结点,最后将end指针指向新结点。
一个结点创建完之后,紧接着要再次分配内存,输入数据,进行while循环。当结点不符合要求时,终止循环,并用free函数将该结点空间进行释放,否则会出现内存泄漏的问题。
❤单链表的遍历
遍历链表中的数据并进行输出。
void print(struct student *head){ struct student *t; //循环所用到的临时指针 int index=1; //链表结点的序号 t=head; //临时指针得到首结点地址 printf("\n**********本名单中有%d个学生**********\n",count); while(t!=NULL) { printf("第%d个学生是:\n",index); //输出结点序号 printf("姓名:%s\n",t->name); //输出姓名 printf("学号:%d\n",t->id); //输出学号 t=t->next; //移动临时指针到下一个结点 index++; //结点序号增加 } printf("\n\n");}
struct student *insert(struct student *head){ struct student *new; printf("输入学生的姓名和学号:\n"); new=(struct student *)malloc(sizeof(struct student)); //给插入的新结点分配内存空间 scanf("%s",new->name); scanf("%d",&new->id); new->next=head; //插入的新结点指向原来的首结点(即得到首结点的地址) head=new; //头指针指向新结点(头->新->原来的首结点) count++; //增加链表结点数量 return head;}
void delete(struct student *head,int index){ int i; struct student *t; //临时指针 struct student *pre; //要删除结点前的结点 t=head; //临时指针得到链表头结点的地址 pre=t; printf("——————删除第%d个学生——————\n",index); for(i=1;inext; } pre->next=t->next; //连接删除结点两边的结点 free(t); //释放要删除结点的内存空间 count--; //减少链表结点个数}
int main(){ struct student *head; //定义头结点 head=create(); //创建结点 print(head); //输出链表 head=insert(head); //插入结点 print(head); //输出链表 delete(head,2); //删除第二个结点 print(head); //输出链表 return 0;}
#include#include struct student //学生结构体{ char name[20]; //姓名 int id; //学号 struct student *next; //指向下一个结点的指针};int count; //全局变量 表示链表长度struct student *create(){ struct student *head=NULL; //初始化头指针为空 struct student *end,*new; end=new=(struct student *)malloc(sizeof(struct student)); count=0; //初始化链表长度 printf("请输入学生的姓名和学号:\n"); scanf("%s",new->name); scanf("%d",&new->id); while(new->id!=0) //当学生学号不为0,执行循环 { count++; if(count==1) //链表中只有一个结点 { new->next=NULL; //新结点的指向为空 end=new; head=new; //新结点既是首结点又是尾结点 } else //链表中结点个数>1 { new->next=NULL; //新结点的指向为空 end->next=new; //原来的尾结点指向新结点 end=new; //新结点当作尾结点 } new=(struct student *)malloc(sizeof(struct student)); //再次分配结点的内存空间 scanf("%s",new->name); scanf("%d",&new->id); } free(new); //释放结点空间 return head;}void print(struct student *head){ struct student *t; //循环所用到的临时指针 int index=1; //链表结点的序号 t=head; //临时指针得到首结点地址 printf("\n**********本名单中有%d个学生**********\n",count); while(t!=NULL) { printf("第%d个学生是:\n",index); //输出结点序号 printf("姓名:%s\n",t->name); //输出姓名 printf("学号:%d\n",t->id); //输出学号 t=t->next; //移动临时指针到下一个结点 index++; //结点序号增加 } printf("\n\n");}struct student *insert(struct student *head){ struct student *new; printf("输入学生的姓名和学号:\n"); new=(struct student *)malloc(sizeof(struct student)); //给插入的新结点分配内存空间 scanf("%s",new->name); scanf("%d",&new->id); new->next=head; //插入的新结点指向原来的首结点(即得到首结点的地址) head=new; //头指针指向新结点(头->新->原来的首结点) count++; //增加链表结点数量 return head;}void delete(struct student *head,int index){ int i; struct student *t; //临时指针 struct student *pre; //要删除结点前的结点 t=head; //临时指针得到链表头结点的地址 pre=t; printf("——————删除第%d个学生——————\n",index); for(i=1;i next; } pre->next=t->next; //连接删除结点两边的结点 free(t); //释放要删除结点的内存空间 count--; //减少链表结点个数}int main(){ struct student *head; //定义头结点 head=create(); //创建结点 print(head); //输出链表 head=insert(head); //插入结点 print(head); //输出链表 delete(head,2); //删除第二个结点 print(head); //输出链表 return 0;}
- 链表——动态存储分配的数据结构
- 数据结构之线性表的线性分配动态存储
- 数据结构——串的堆分配存储
- 数据结构(四)C++动态存储分配
- 动态存储分配及深复制 —字符串的复制
- 数据结构随笔—动态存储管理
- 数据结构基础——指针及动态内存分配(malloc)
- C语言——存储类和动态内存分配
- 动态存储分配及深复制——人数不定的工资类
- 动态存储分配及深复制 —字符串的复制2
- 动态存储分配及深复制 —我的数组类
- 函数运行时的动态存储分配
- C++中动态存储分配的基础知识
- 动态存储分配
- 动态存储分配
- 动态存储分配
- 动态存储分配
- 动态存储分配
- 在CentOS 7上面安装maven
- Java正则表达式
- Linux下c语言多线程编程
- javascript定时器的应用
- Linux下查找软件
- 链表——动态存储分配的数据结构
- 栈的顺序存储结构
- IMWeb提升营 | 第二次课堂直播笔记:认真的聊聊前端开发面试
- R语言利用igraph和networkD3包快速入门做出炫酷的社交网络图等几类图。
- 网络流之最大流(FF, EK, Dinic, SAP)
- Linux ELF文件格式分析
- 5月占位
- MySQL学习笔记(2)
- 5月占位2