在说链表之前,我们先说说顺序存储。其中我们最熟悉的一种顺序存储的数据结构就是数组,当我们想要给数组中插入一个元素时,为保证顺序以及其他元素不丢失,我们需要在插入元素后,将后面的元素整体后移。所以容易看出这样有着这两个弊端:第一:我们所需要移动的元素有很多时,会浪费算力。第二:我们必须为数组开足够多的空间,否则会存在溢出风险。
为了避免这两个弊端,我们引入链式存储——链表。
什么是链表?
简单来说,链表的利用结构体,额外开辟出一份内存空间去作指针,它总是指向下一个结点,一个个结点通过指针相互串联,这就形成了我们的链表。
其中DATA数据元素(数据域),可以是int类型或char类型,甚至可以是结构体。NEXT为一个指针通常是用来指向下一个结点,链表的尾部NEXT指向NULL,因为它没有可以指向的空间了。
对于一个单链表的结点定义:
``
1 //定义结点类型 2 typedef struct Node 3 { 4 int DATA;//数据域 5 struct Node* NEXT;//指针域 6 }Node,* pointnode;//Node表示结点的类型,pointnode表示指向Node结点类型的指针类型 7 ``` 8 1.对链表进行初始化: 9 10 ```c 11 pointnode Initialize() 12 { 13 Node* H=(Node*)malloc(sizeof(Node)); //开辟空间 14 if(H==NULL) //判断是否开辟成功 15 { 16 printf("开辟失败!");//开辟失败的提示 17 exit(0); // 开辟失败结束程序(根据情况看是否添加) 18 } 19 H->NEXT=NULL; //指针指向NULL 20 } 21 ``` 22 2.创建单链表: 23 <1>头插法 24 从一个空表开始,生成新结点,并将数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头即头结点之后。 25 ```c 26 pointnode listofhead() 27 { 28 Node* H = (Node*)malloc(sizeof(Node));//开辟一个头空间 29 H -> NEXT= NULL; //初始化为空 30 31 int x; 32 while (scanf("%d", &x) != EOF) //输入数据,当输入空的时候停止(在Windows下:Ctrl+Z) 33 { 34 Node* p = (Node*)malloc(sizeof(Node)); 35 p->DATA = x; //赋值给数据域 36 p->NEXT = H->NEXT; //将节点插到表头 37 H->NEXT = p; 38 } 39 return H; 40 } 41 ``` 42 <2>尾插法 43 将新结点逐个插入到当前链表的表尾上,增加一个尾指针, 使其始终指向当前链表的尾结点。 44 ```c 45 pointnode listofend() 46 { 47 Node* H = (Node*)malloc(sizeof(Node)); //开辟头空间 48 H->NEXT = NULL; //初始化 49 50 int x; 51 Node* l; //定义为尾指针 52 l = H; // 尾指针开始指向头,始终指向尾。 53 while (scanf("%d", &x) != EOF) 54 { 55 Node* p = (Node*)malloc(sizeof(Node)); 56 p->DATA = x; 57 l->NEXT = p; //将结点插到表头 58 l = p; 59 60 } 61 l->NEXT = NULL; 62 return H; 63 } 64 ``` 65 注意:头插法的顺序是逆序的:表头->[n]->···->[2]->[1]->NULL 66 尾插法是正序的:表头->[1]->[2]->····[n]->NULL 67 3.链表的遍历 68 69 ```c 70 void listoftravel(pointnode H) 71 { 72 Node* p = H->NEXT; 73 74 int i = 1; 75 while (p) 76 { 77 printf("第%d个数据是%d\n", i++, p->DATA); 78 p = p->NEXT; 79 } 80 81 }
2.链表的插入
1 //链表的插入 2 pointnode datainlist(pointnode H,int i,int x) 3 { 4 Node* preve = H; 5 int seek; 6 for (seek = 1; seek < i; seek++)//寻找元素位置 7 { 8 preve = preve->NEXT; 9 } 10 Node* p = (Node*)malloc(sizeof(Node)); 11 p->DATA = x; 12 p->NEXT = preve->NEXT; 13 preve->NEXT = p; 14 return H; 15 }
3.链表修改
//链表的修改 pointnode moddata(pointnode H,int x,int t) { Node* p = H->NEXT; while (p) { if (p->DATA == x) { p->DATA = t; } p = p->NEXT; } return H; }
4.链表删除
//链表的删除 pointnode freedata(pointnode H,int x) { Node* p; Node* preve;//前驱结点 p = H->NEXT; while (p->DATA != x)//查找元素 { preve = p; p = p ->NEXT; } preve->NEXT = p->NEXT; free(p); //删除操作 return H; }
5.完整代码

#include<stdio.h> #include<stdlib.h> //定义结点类型 typedef struct Node { int DATA;//数据域 struct Node* NEXT;//指针域 }Node, * pointnode; //Node表示结点的类型,pointnode表示指向Node结点类型的指针类型 //链表的初始化 pointnode Initialize() { Node* H = (Node*)malloc(sizeof(Node)); //开辟空间 if (H == NULL) //判断是否开辟成功 { printf("开辟失败!");//开辟失败的提示 exit(0); // 开辟失败结束程序(根据情况看是否添加) } H->NEXT = NULL; //指针指向NULL } //头插法建立链表 pointnode listofhead() { Node* H = (Node*)malloc(sizeof(Node));//开辟一个头空间 H = NULL; //初始化为空 int x; while (scanf("%d", &x) != EOF) //输入数据,当输入空的时候停止(在Windows下:Ctrl+Z) { Node* p = (Node*)malloc(sizeof(Node)); p->DATA = x; //赋值给数据域 p->NEXT = H->NEXT; //将节点插到表头 H->NEXT = p; } return H; } //尾插法 pointnode listofend() { Node* H = (Node*)malloc(sizeof(Node)); //开辟头空间 H->NEXT = NULL; //初始化 int x; Node* l; //定义为尾指针 l = H; // 尾指针开始指向头,始终指向尾。 while (scanf("%d", &x) != EOF) { Node* p = (Node*)malloc(sizeof(Node)); p->DATA = x; l->NEXT = p; //将结点插到表头 l = p; } l->NEXT = NULL; return H; } //遍历链表 void listoftravel(pointnode H) { Node* p = H->NEXT; int i = 1; while (p) { printf("第%d个数据是%d\n", i++, p->DATA); p = p->NEXT; } } //链表的插入 pointnode datainlist(pointnode H,int i,int x) { Node* preve = H; int seek; for (seek = 1; seek < i; seek++)//寻找元素位置 { preve = preve->NEXT; } Node* p = (Node*)malloc(sizeof(Node)); p->DATA = x; p->NEXT = preve->NEXT; preve->NEXT = p; return H; } //链表的修改 pointnode moddata(pointnode H,int x,int t) { Node* p = H->NEXT; while (p) { if (p->DATA == x) { p->DATA = t; } p = p->NEXT; } return H; } //链表的删除 pointnode freedata(pointnode H,int x) { Node* p; Node* preve;//前驱结点 p = H->NEXT; while (p->DATA != x)//查找元素 { preve = p; p = p ->NEXT; } preve->NEXT = p->NEXT; free(p); //删除操作 return H; } int main() { pointnode list; Initialize(); list = listofend(); //list = listofhead(); listoftravel(list); //链表的修改 int x; int t; printf("你想修改的数据是:"); scanf("%d", &x); printf("你想把他改为:"); scanf("%d", &t); moddata(list, x, t); listoftravel(list); //链表的插入 int i; printf("你想在哪个位置插入数据:"); scanf("%d", &i); printf("你想插入的数据是:"); scanf("%d", &x); datainlist(list, i, x); listoftravel(list); //链表的删除 printf("你想删除的数据是:"); scanf("%d", &x); freedata(list, x); listoftravel(list); return 0; }
希望大家也可以关注本人的CSDN,内容都是一致的!如有错误,请指正!!