赞
踩
前言:今天花了一下午时间学习了链表,讲自己所学内容分享给大家,本篇内容对于链表的使用进行了非常详细的讲解,搭配代码的编写事半功倍,希望对大家有所帮助,喜欢的可以一键三连(点赞,收藏,评论)
顺序表:以数组的形式存放,元素在内存中是连续存放的
特点:插入或删除一个数据元素时,需要移动其他数据元素
(线性)链表:数据元素在内存中不需要连续存放,而是通过指针将个数据单元链接起来,就像一条”链子“一样将数据单元前后元素链接起来
特点:插入或删除一个数据元素时,不需要移动其他数据元素
线性链表的节点可以用一个结构体类型来定义,其形式为
- struct 结构体类型名
- {
- 数据成员定义;
- struct 节点结构体类型名 *指针变量名;
- };
-
- 例子:
- struct GRADE_iInfo
- {
- int score;
- struct GRADE_iInfo *next;
- };
- typedef struct GRADE_iInfo NODE;//类型重命名
节点包括:数据域和指针域
数据域:存放本节点的数据
指针域:存放下一节点的地址
头节点指针:存放第一个节点的指针(在下面创建链表中有详细图解)
基本操作有:创建,插入,删除,输出,销毁
以题目为例:
建立一个学生成绩的线性链表,然后对其进行插入,删除,显示,最后销毁该链表
- #include<stdio.h>
- #include<stdlib.h>//动态内存函数的头文件
- //创建结构体类型,因为节点可以用结构体类型来定义
- struct Grade_Info
- {
- int score;
- struct Grade_Info *next;//节点的基类型要和节点的类型一致,相当于结构体的自引用
- };
- typedef struct Grade_Info NODE;//类型重命名
- //函数声明
- NODE*Creat_LinkList();//创建链表
- void Insert_LinkList(NODE*head,NODE*pnew,int i);//插入节点
- void Delete_LinkList(NODE*head,int i);//删除节点
- void Display_Linklist(NODE*head);//输出链表
- void Free_LinkList(NODE*head);//销毁链表
- int main()
- {
- NODE*head = NULL;//头节点
- NODE*pnew = NULL;//存放新节点的地址
- head = Creat_LinkList();//创建链表
- if(head == NULL)//创建失败
- return 0 ;
- printf("after creat:");
- Display_Linklist(head);//输出链表的值
- //新建一个要插入的节点
- pnew = (NODE*)malloc(sizeof(NODE));//动态内存开辟
- if(pnew == NULL)//新节点创建失败,则返回
- {
- printf("no enough memory\n");
- return 0;
- }
- pnew->score = 88;
- //将新节点插入节点2的后面
- Insert_LinkList(head,pnew,2);
- return 0;
- }
含义:从无到有创建一个链表,即往空链表中依次插入若干个节点,并保持节点之间的前驱和 后继关系
基本思想:首先创建一个头节点,让头指针(head)和尾指针(tail)都指向该节点,并设置该节点的指针域为NULL(链尾标志);然后为实际数据创建一个节点,用指针pnew(用来存放新节点的地址)指向它,并将实际数据放在该节点的数据域,其指针与为NULL;最后将该节点插入到tail所指向节点的后面,同时时tail指向pnew指向的节点
- NODE*Creat_LinkList()
- {
- NODE*head = NULL;//头节点
- NODE*tail = NULL;//尾节点
- NODE*pnew = NULL;//存放新节点的地址
- int score = 0;
- head = (NODE*)malloc(sizeof(NODE));//创建头节点
- if(head==NULL)
- {
- printf("no enough memory!\n");
- return NULL;
- }
- head->next = NULL;
- tail = head;
- printf("intput the score of students:\n");
- while(1)//创建学生成绩线性链表
- {
- scanf("%d",&score);//输入成绩
- if(score<0)//成绩为负,循环退出
- {
- break;
- }
- //创建一个新的节点,存放成绩
- pnew = (NODE*)malloc(sizeof(NODE));
- if(pnew == NULL)
- {
- printf("no enough memory!\n");
- return NULL;
- }
- pnew->score = score;
- pnew->next = NULL;
- tail->next = pnew;
- tail = pnew;
- }
- return head;
- }
基本思想:通过单链表的头指针head,首先找到链表的第一个节点;然后顺着节点的指针域找到第i个节点,最后将pnew指向的新节点插入到第i个节点之后。插入时首先将新节点的指针域指向第i个节点的后继节点,然后再将第i个节点的指针域指向新节点。注意顺序不能颠倒。当i=0时;表示头节点
- void Insert_LinkList(NODE*head,NODE*pnew,int i)
- {
- //i == 2
- NODE*p = NULL;
- int j = 0;
- p = head;
- for(j = 0;j<i&&p!=NULL;j++)//将p指向要插入的第i个节点
- {
- p = p->next;
- }
- if(p == NULL)//表明链表中的第i个节点不存在
- {
- printf("the %d nonde not found\n",i);
- return;
- }
- pnew->next = p->next;;//将插入节点的指针域指向第i个节点后继节点
- p->next=pnew;//将第i个节点的指针域指插入的节点
- }
- void Delete_LinkList(NODE*head,int i)
- {
- NODE*p = NULL;
- NODE*q = NULL;
- int j = 0;
- if(i == 0)//删除的是头指针
- {
- return ;
- }
- p = head;
- //将p指向要删除的第i个节点的前驱节点
- for(j = 1;j<i&&p->next!=NULL;j++)
- {
- p = p->next;
- }
- if(p->next == NULL)//表明要删除的第i个节点不存在
- {
- printf("the %d node not found\n",i);
- return;
- }
- q = p->next;//q指向待删除的节点i
- p->next = q->next;//删除节点i
- free(q);//释放节点的内存单元
- }
- void Display_Linklist(NODE*head)
- {
- NODE*p = NULL;
- for(p = head->next;p!=NULL;p = p->next)//注意区分节点的地址和节点的指针域
- {
- printf("%d ",p->score);
- }
- printf("\n");
- }
基本思想:每次删除头节点的后继节点,最后删除头节点。注意,不是删除了头节点就可以删除震整个链表,要知道链表是一个节点一个接待你建立起来的,所以销毁它也必须一个节点一个节点的删除才行
- void Free_LinkList(NODE*head)
- {
- NODE*p = NULL;
- NODE*q = NULL;
- p = head;
- while(p->next != NULL)
- {
- q = p->next;
- p->next = q->next;
- free(q);
- }
- free(head);
- }
- #include<stdio.h>
- #include<stdlib.h>//动态内存函数的头文件
- //创建结构体类型,因为节点可以用结构体类型来定义
- enum choice
- {
- no,//0
- yes//1
- };
- struct Grade_Info
- {
- int score;
- struct Grade_Info* next;//节点的基类型要和节点的类型一致,相当于结构体的自引用
- };
- typedef struct Grade_Info NODE;//类型重命名
- //函数声明
- NODE* Creat_LinkList();//创建链表
- void Insert_LinkList(NODE* head, NODE* pnew, int i);//插入节点
- void Delete_LinkList(NODE* head, int i);//删除节点
- void Display_Linklist(NODE* head);//输出链表
- void Free_LinkList(NODE* head);//销毁链表
- int main()
- {
- NODE* head = NULL;//头节点
- NODE* pnew = NULL;//存放新节点的地址
- head = Creat_LinkList();//创建链表
- if (head == NULL)//创建失败
- return 0;
- printf("after creat:");
- Display_Linklist(head);//输出链表的值
- printf("是否要插入一个学生的成绩?是:1,否:0\n");
- int n = 0;
- scanf("%d", &n);
- switch (n)
- {
- case no:
- break;
- case yes:
- {
- int i = 0;
- printf("要插入到第几个学生后?\n");
- scanf("%d", &i);
- //新建一个要插入的节点
- pnew = (NODE*)malloc(sizeof(NODE));//动态内存开辟
- if (pnew == NULL)//新节点创建失败,则返回
- {
- printf("no enough memory\n");
- return 0;
- }
- int score = 0;
- printf("输入插入学生的成绩:");
- scanf("%d", &score);
- pnew->score = score;
- Insert_LinkList(head, pnew,i );//将新节点插入节点n的后面
- printf("afte insert:");
- Display_Linklist(head);//输出链表的值
- }
- }
- printf("要删除某个学生的成绩吗?是:1,否:0\n");
- int m = 0;
- scanf("%d", &m);
- switch (m)
- {
- case no:
- break;
- case yes:
- {
- int i = 0;
- printf("要删除第几个学生的成绩?请输入:");
- scanf("%d", &i);
- Delete_LinkList(head,i);
- printf("after Delete:");
- Display_Linklist(head);//输出链表的值
- }
- }
- //没有以上操作就销毁链表
- Free_LinkList(head);
- return 0;
- }
- //创建链表
- NODE* Creat_LinkList()
- {
- NODE* head = NULL;//头节点
- NODE* tail = NULL;//尾节点
- NODE* pnew = NULL;//存放新节点的地址
- int score = 0;
- head = (NODE*)malloc(sizeof(NODE));//创建头节点
- if (head == NULL)
- {
- printf("no enough memory!\n");
- return NULL;
- }
- head->next = NULL;
- tail = head;
- printf("intput the score of students:\n");
- while (1)//创建学生成绩线性链表
- {
- scanf("%d", &score);//输入成绩
- if (score < 0)//成绩为负,循环退出
- {
- break;
- }
- //创建一个新的节点,存放成绩
- pnew = (NODE*)malloc(sizeof(NODE));
- if (pnew == NULL)
- {
- printf("no enough memory!\n");
- return NULL;
- }
- pnew->score = score;
- pnew->next = NULL;
- tail->next = pnew;
- tail = pnew;
- }
- return head;
- }
- //插入节点
- void Insert_LinkList(NODE* head, NODE* pnew,int i)
- {
- //i == 2
- NODE* p = NULL;
- int j = 0;
- p = head;
- for (j = 0; j < i && p != NULL; j++)//将p指向要插入的第i个节点
- {
- p = p->next;
- }
- if (p == NULL)//表明链表中的第i个节点不存在
- {
- printf("the %d nonde not found\n", i);
- return;
- }
- pnew->next = p->next;;//将插入节点的指针域指向第i个节点后继节点
- p->next = pnew;//将第i个节点的指针域指插入的节点
- }
- //删除节点
- void Delete_LinkList(NODE* head, int i)
- {
- NODE* p = NULL;
- NODE* q = NULL;
- int j = 0;
- if (i == 0)//删除的是头指针
- {
- return;
- }
- p = head;
- //将p指向要删除的第i个节点的前驱节点
- for (j = 1; j < i && p->next != NULL; j++)
- {
- p = p->next;
- }
- if (p->next == NULL)//表明要删除的第i个节点不存在
- {
- printf("the %d node not found\n", i);
- return;
- }
- q = p->next;//q指向待删除的节点i
- p->next = q->next;//删除节点i
- free(q);//释放节点的内存单元
- }
- //输出链表
- void Display_Linklist(NODE* head)
- {
- NODE* p = NULL;
- for (p = head->next; p != NULL; p = p->next)//注意区分节点的地址和节点的指针域
- {
- printf("%d ", p->score);
- }
- printf("\n");
- }
- //销毁链表
- void Free_LinkList(NODE* head)
- {
- NODE* p = NULL;
- NODE* q = NULL;
- p = head;
- while (p->next != NULL)
- {
- q = p->next;
- p->next = q->next;
- free(q);
- }
- free(head);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。