Loading... ## 简介: * **定义**:链表是一种**物理储存**上**非连续**,结构元素的逻辑顺序通过链表中的指针链接次序,实现的一种**线性**储存结构。 * **特点**:链表由一系列节点(链表中每一个元素称为节点)组成,节点在运行时**动态生成(malloc)**,每个节点包括两个部分: 1. 一个是储存数据元素的**数据域** 2. 另一个是储存下一个节点地址的**指针域** # 链表的构成: 1. 数据域:存数据 2. 指针域:指向下一个节点的地址 ![示意图](https://blog.fivk.cn/usr/uploads/2021/01/2549077484.jpg) * 每个节点是没有名字的 * 每个节点都需要调用一次maollc * 调用的一个maollc空间是连续的 * 但是两个maollc空间不一定是连续的 # 链表节点的定义(结构体实现): ```C //学生管理系统举例 typedef struct str { //数据域(自定义) int num; char name[32]; float score; //指针域() struct stu* next; //保存下一个节点的地址,不能用STU。 //应为STU编译器还没有识别,不认识。 }STU; ``` ### 静态链表: ```C #include<stdio.h> //学生管理系统举例 typedef struct stu { //数据域(自定义) int num; char name[32]; float score; //结构域() struct stu* next; //保存下一个节点的地址,不能用STU。 //应为STU编译器还没有识别,不认识。 }STU; void test1() { STU data1 = { 100,"小帆",59 }; STU data2 = { 101,"小宇",61 }; STU data3 = { 102,"小安",71 }; STU data4 = { 103,"小陈",45 }; STU data5 = { 104,"小霓",59 }; //链表头 STU* head = NULL; head = &data1; data1.next = &data2; data2.next = &data3; data3.next = &data4; data4.next = &data5; data5.next = NULL; //遍历列表 STU* pb = head; while (pb != NULL) { printf("%d %s %f\n",pb->num,pb->name,pb->score); pb = pb->next;//pb移动到下一个节点 } } int main(int argc, char* argv[]) { test1(); return 0; } ``` ### 动态链表: **1.布局整个程序操作** ```C #include<stdio.h> #include<string.h> void stu_help(void); int main(int argc, char* argv[]) { stu_help(); while (1) { printf("请输入操作指令:"); char cmd[6] = ""; scanf("%s", cmd); if (strcmp(cmd, "help") == 0) { stu_help();//帮助 } else if (strcmp(cmd, "insert") == 0) { printf("_______insert______"); } else if (strcmp(cmd, "print") == 0) { printf("_______printf_______"); } else if (strcmp(cmd, "search") == 0) { printf("_______search______"); } else if (strcmp(cmd, "delete") == 0) { printf("_______delete______"); } else if (strcmp(cmd, "free") == 0) { printf("_______free______"); } else if (strcmp(cmd, "quit") == 0) { break; } } return 0; } //帮助 void stu_help(void) { printf("############################\n"); printf("# help:打印帮助信息 #\n"); printf("# insert:插入链表节点 #\n"); printf("# print:遍历链表节点信息 #\n"); printf("# search:查询链表节点 #\n"); printf("# delete:删除链表节点 #\n"); printf("# free:释放链表节点 #\n"); printf("# quit:退出 #\n"); printf("############################\n"); } ``` **2.链表插入节点(头部之前插入)** ![带头节点与不带头节点](https://blog.fivk.cn/usr/uploads/2021/01/3509182319.jpg) * 带头节点是以一个无数据节点为head * 不带头节点为4个字节(推荐) ![原理示意图](https://blog.fivk.cn/usr/uploads/2021/01/2476390395.jpg) !<div class="list-group list-group-lg list-group-sp row" style="margin: 0"></div>(https://blog.fivk.cn/usr/uploads/2021/01/3914540410.png) **插入链表:main.c link.c link.h** * main.c ```C #include<stdio.h> #include<string.h> #include<stdlib.h> #include "link.h" void stu_help(void); void print_link(STU* head); int main(int argc, char* argv[]) { //定义一个链表头 注意一定要赋值为NULL STU* head = NULL; stu_help(); while (1) { char cmd[6]=""; printf("请输入操作指令:"); scanf("%s", cmd); if (strcmp(cmd, "help") == 0) { stu_help();//帮助 } else if (strcmp(cmd, "insert") == 0) { STU tmp; printf("请输入需要插入的数据:"); scanf("%d %s %f", &tmp.num, tmp.name, &tmp.score); //将tmp数据插入到head所指向的链表中 head = insert_link(head, tmp);//也可以传递二级指针&head } else if (strcmp(cmd, "print") == 0) { print_link(head); } else if (strcmp(cmd, "search") == 0) { printf("_______search______"); } else if (strcmp(cmd, "delete") == 0) { printf("_______delete______"); } else if (strcmp(cmd, "free") == 0) { printf("_______free______"); } else if (strcmp(cmd, "quit") == 0) { break; } } return 0; } //帮助 void stu_help(void) { printf("############################\n"); printf("# help:打印帮助信息 #\n"); printf("# insert:插入链表节点 #\n"); printf("# print:遍历链表节点信息 #\n"); printf("# search:查询链表节点 #\n"); printf("# delete:删除链表节点 #\n"); printf("# free:释放链表节点 #\n"); printf("# quit:退出 #\n"); printf("############################\n"); } ``` * link.c ```C #include<stdlib.h> #include<stdio.h> #include "link.h" void stu_help(void); STU* insert_link(STU *head,STU tmp) { //1、从堆区申请一个等待插入的节点空间 STU* pi = (STU*)calloc(1, sizeof(STU)); if (pi == NULL) { perror("calloc"); return head; } //2、将tmp的值,赋值给 *pi *pi = tmp; pi->next = NULL; //3/将pi插入到链表中 if (head == NULL) { //链表不存在 head = pi; } else { //链表存在(头部之前插入 //1、让pi 指向旧的头 pi->next = head; //2、head指向新的头节点 head = pi; } return head; } void print_link(STU* head) { if (head == NULL) { //链表不存在 printf("link not find\n"); return; } else { //遍历 STU* pb = head; while (pb != NULL) { printf("%d %s %f\n", pb->num, pb->name, pb->score); //pb指向下一个节点 pb = pb->next; } } return; } ``` * link.h ```C //#pragma once //防止头文件重复包含 #ifndef __LINK_H_ #define __LINK_H_ //链表节点类型定义 typedef struct stu { //数据域 int num; char name[32]; float score; //指针域 struct stu* next; }STU; extern STU* insert_ilnk(STU *head, STU tmp); extern void print_link(STU* head); #endif ``` <iframe class="iframe_video" src="//player.bilibili.com/player.html?aid=372528286&bvid=BV1XZ4y1G7No&cid=249273551&page=55" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe> <div class="tip inlineBlock info"> 又1点了,这篇文章写了几天。。哎,主要是懒。。 </div> 最后修改:2021 年 02 月 21 日 © 禁止转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏