链表如何速成


如果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;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值