代码参考《妙趣横生的算法.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域

代码描述:

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:

【数据结构基础笔记】【链表】相关推荐

  1. Python数据结构学习笔记——链表:无序链表和有序链表

    目录 一.链表 二.无序链表 实现步骤分析 三.无序链表的Python实现代码 四.有序链表 实现步骤分析 五.有序链表的Python实现代码 结语 一.链表 链表中每一个元素都由为两部分构成:一是该 ...

  2. 算法与数据结构基础四----数据结构基础之动态数据结构基础:链表上

    接着上一次https://www.cnblogs.com/webor2006/p/15195969.html的数据结构继续往下学习,这次会进入一个非常重要的数据结构的学习----链表,这个是未来学习复 ...

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

    代码参考<妙趣横生的算法.C语言实现> 文章目录 前言 1.栈的定义 2.创建一个栈 3.入栈和出栈操作 4.栈的清空.销毁.计算栈的当前容量 5.实例分析 前言 本章总结:栈的定义.创建 ...

  4. 【数据结构基础笔记】【树】

    代码参考<妙趣横生的算法.C语言实现> 文章目录 前言 1.树的概念 2.二叉树 3.二叉树的遍历 4.创建二叉树 5.实例分析 前言 本章总结:树的概念.二叉树的创建.遍历 1.树的概念 ...

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

    代码参考<妙趣横生的算法.C语言实现> 文章目录 前言 1.队列定义 2.创建一个队列 3.入队列 4.出队列 5.销毁一个队列 6.循环队列的概念 7.循环队列的实现 8.实例分析 前言 ...

  6. 数据结构基础篇-链表反转(非递归与递归)C++实现

    链表反转C++代码,附加打印逆序链表(不进行反转)代码. 测试用例: 5 2 3 4 10 5 1 4 1.非递归实现 思路:需要三个指针p1.p2.p3,分别指向上一个节点.当前节点与缓存的下一个节 ...

  7. 【数据结构基础笔记】【顺序表】

    代码参考<妙趣横生的算法.C语言实现> 文章目录 前言 1.创建顺序表 2.顺序表插入元素 3.顺序表删除元素 4.顺序表实例分析 1.静态 2.动态 5.顺序表总结 前言 本章总结:从静 ...

  8. 【数据结构基础】之链表介绍,生动形象,通俗易懂,算法入门必看

    前言 本文为 数据结构基础[链表] 相关知识,下边将对链表概念,单链表,双链表,循环链表,Java中链表的使用等进行详尽介绍~

  9. 一周刷爆LeetCode,算法da神左神(左程云)耗时100天打造算法与数据结构基础到高级全家桶教程,直击BTAJ等一线大厂必问算法面试题真题详解 笔记

    一周刷爆LeetCode,算法大神左神(左程云)耗时100天打造算法与数据结构基础到高级全家桶教程,直击BTAJ等一线大厂必问算法面试题真题详解 笔记 教程与代码地址 P1 出圈了!讲课之外我们来聊聊 ...

最新文章

  1. IIS配置跨服务器迁移
  2. python计算奖金_2020还有3个月,收了这套Python资料,年终奖翻倍!
  3. 12.8 线程和信号
  4. linux系统下PHP无法调用oracle数据库的解决方法
  5. IE6 Hack(转载)
  6. 为什么jQuery或诸如getElementById之类的DOM方法找不到元素?
  7. 参观移动公司机房感想
  8. nginx 内置变量大全
  9. 非线性控制3.0——自适应模糊控制
  10. 2020SpringCloud学习年终总结——第九章-Gateway
  11. mysql 子链接_MySQL多表查询实例详解【链接查询、子查询等】
  12. 再见python你好go语言_再见,Python!你好,Go语言
  13. “数据结构基础”系列网络课程主页
  14. Activity的数据回传——案例:装备选择
  15. 1188_什么是TVS管_瞬态抑制二极管
  16. linux 编辑my.cnf,linux下 vi命令编辑/etc/my.cnf
  17. 计算机win7卡顿如何解决方法,win7电脑运行很慢很卡怎么办
  18. 社区团购前端(uniapp)加后端系统源码
  19. 资源搜索,推荐3个比网盘搜索质量度高的平台和技巧!
  20. 通过PS把暗调照片调出清新色调

热门文章

  1. 图谱(学习地图)系列总结,持续更新中
  2. 一文教你用java实现儿时的超级玛丽游戏
  3. DVWA通关教程(中)
  4. java怎么生成字母_java自动生成字母
  5. gateway 过滤器执行顺序_Gateway网关源码解析—路由(1.1)之RouteDefinitionLocator一览...
  6. 结合WebSocket编写WebGL综合场景示例
  7. 房价在手,天下我有 --反手就撸一个爬虫(终)
  8. 从0开始接触html--第一天学习内容总结
  9. Springboot + Mybatis + Ehcache
  10. 结构化日志:出错时你最想要的好朋友