如果C语言老师讲完指针就让你写链表,就来看看这个
ps:只是一些我对链表的理解,可以用来速成和入门
链表
看图,这个是数组:
数组可以理解为:一些地址连续的变量的集合 (都学完指针了,就不要问我地址是什么了吧~~)
再看图,这个是链表:
链表可以理解为:一些地址不连续的变量的集合 (都学完指针了,就不要问我地址是什么了吧~~)
这个时候可以问了 ,既然都是集合,为什么不直接用数组?
数组因为地址连续,可以很快的去找到第 i 个元素的位置,操作方便。but,连续的地址意味着在定义数组时,要预留出来足够的空间才行。那么问题就来了,留多大的空间合适?
多了少了都不是太好,所以链表就出现了。
链表的每一个结点都有一个指针,用来指向下一个结点的地址。
通过指针,就可以实现各种功能(主要的功能就是‘增删改查’)。
链表说白了,就是一个 head结点(没数据) 指向了第一个结点(有数据),第一个结点指向了第二个结点,第二个结点指向了第三个结点 . . . . . . 一直到最后一个结点指向 NULL
添加数据
链表添加数据,主要有头插入法和尾插入法。
看图演示一下头插入法:
- 让新节点指向第一个结点
- 让head结点指向新节点
- 这时,新结点就插入到链表的头部了
- 完工
ps:尾插入法自己意会吧
删除第 x 个结点
这里我们删除第三个结点(x = 3),用黄色箭头表示在第几个结点。
- 先找到第 x-1 个结点
指针套娃,套到如图所示的位置
- 让第 x-1 个结点的指针,指向第 x + 1 个结点
- 把第 x 个结点的空间回收
- 完工
ps:这里可以想一下删除最后一个结点要如何操作,参考代码里有操作
改和查的操作
这两个操作类似于删的操作,类比即可。
参考代码
#include <stdio.h>
#include <stdlib.h>
// 链表
typedef struct Node{
int data;
struct Node *next;
} List;
// 初始化
void init(List * &a){
a = (List *)malloc(sizeof(List));
a->next = NULL;
}
// 添加数据
void add(List * &a, int data){
List *now = (List *)malloc(sizeof(List));
now->data = data;
now->next = a->next;
a->next = now;
}
// 删除数据
void del(List * &a, int pos){
if(pos == 0){
printf("del error! pos = %d\n", pos);
return ;
}
List *now = a, *tmp;
for(int i = 1; i < pos && now != NULL; i++) now = now->next;
if(now == NULL || now->next == NULL){
printf("del error! pos = %d\n", pos);
return ;
}
tmp = now->next;
now->next = tmp->next;
free(tmp); // 释放空间
}
// 可以找到返回真
bool find(List *a, int x){
List *now = a->next;
while(now != NULL){
if(now->data == x){
return 1;
}
now = now->next;
}
return 0;
}
// 得到链表的大小
int get_size(List *a){
int size = 0;
List *now = a->next;
while(now != NULL){
size++;
now = now->next;
}
return size;
}
// 重载函数,输出链表
void printf(List *a){
int size = get_size(a);
if(size == 0){
printf("链表为空\n");
return;
}
List *now = a->next;
while(now != NULL){
printf("(%d) ", now->data);
now = now->next;
}
printf("\n");
}
// 重载函数,输出链表从 start 开始的 cnt 个函数
void printf(List *a, int start, int cnt){
List *now = a;
for(int i = 1; i <= start; i++) now = now->next;
for(int i = 1; i <= cnt; i++){
printf("(%d) ", now->data);
now = now->next;
}
}
int main(int argc, char *argv[]) {
List *L1;
init(L1);
add(L1, 5);
printf(L1);
del(L1, 1);
printf(L1);
return 0;
}