2021-04-11

链表总结(c语言实现)

关于链表的操作主要包括4种
1 单链表
2单向循环
3双向链表
4双向循环
具体操作如下
1 单链表(包括带头结点与不带头结点的,带头结点的在尾删时不需要考虑第一个节点是否存在,尾插不需要考虑是不是有结点存在)
类型定义

typedef struct slnode {//结构体类型
	int data;//存放数据
	struct slnode* next;//存放下一个位置的指针
}slonde;
slonde* plist=NULL;//头指针

先看不带头结点的(包括尾插,头插,尾删,头删,在第i个节点后插入)
尾插

slnode* creatnode(int x) {//创建一个节点
	slnode* newnode = (slnode*)malloc(sizeof(slnode));
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
void spushtail(slnode** pphead) {//尾插,需要改变plist指向位置,传地址
	int x;//为插入数据值
	scanf("%d", &x);
	slnode* newnode = creatnode(x);
	if (*pphead == NULL) {//如果不讨论后面cur->next会报错
		*pphead = newnode;
	}
	else {
		slnode* cur = *pphead;//用尾指针指向下一个结点
		while (cur->next) {//注意是cur->next,如果是cur下面cur->next会报错,其实这个循环的作用是方便多次调用每次尾指针都指向最后一个结点
			cur = cur->next;
		}
		cur->next = newnode;
	}
}
void sprint(slnode* phead) {//打印链表
	while (phead) {
		printf("%d->",phead->data);
		phead = phead->next;
	}
	printf("NULL\n");
}

尾删

oid spoptail(slnode** pphead) {//尾删,可能对plist指向发生改变在最后一次删除时指向改为空
	if (*pphead == NULL) {
		*pphead=NULL;
	}
	if ((*pphead)->next == NULL) {//需要对第一个结点进行判断,不然后面第一个结点不会被置空
		*pphead=NULL;
	}
	else {//需要一个前指针指向最后一个结点前面,将前面节点的next置空和一个指针判断是不是到达尾部
		slnode *pre= *pphead;
		slnode *cur= *pphead;
		while (cur->next) {
			pre = cur;
			cur = cur->next;
		}
		pre->next = NULL;
		free(cur);//释放空间
		
	}
}

头插

void spushhead(slnode** pphead){//头插
	int x;
	scanf("%d", &x);
	slnode* newnode = creatnode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

头删

void spophead(slnode** pphead) {
	if (*pphead == NULL) {
		*pphead = NULL;
	}
	else {//需要一个前指针指向被删除的,后指针指向需要连接的
		slnode *pre= *pphead;
		slnode *cur= (*pphead)->next;
		*pphead = cur;
	}
}

在第i个结点后插入

void sinsert(slnode** pphead) {//在某个结点后插入,传值传地址都可以,如果在第一个结点插入就要传递地址
	slnode* cur = *pphead;//新结点链接cur
	slnode* pre = *pphead;//通过pre链接新结点
	int i;
	int count = 0;
	scanf("%d", &i);//插入位置
	while (cur) {
		pre = cur;
		count++;
		cur = cur->next;
		if (count == i) {
			break;
		}

	}
	int x;
	scanf("%d", &x);
	slnode* newnode = creatnode(x);
	newnode->next = cur;
	pre->next = newnode;
}

带头结点的(尾插,尾删)//还有的操作就不列举了,方法类似
尾插

void shpushtail(slnode** pphead) {
	
	slnode* head = creatnode(1);//头结点,注意当多次调用这个函数时需要对是不是要创建头结点进行讨论,需要添加多个节点在此函数加入循环即可
	*pphead = head;
	slnode* cur = head;
	int x;
	scanf("%d", &x);
	slnode* newnode = creatnode(x);
	cur->next = newnode;


}
void shprint(slnode* phead) {
	phead = phead->next;//跳过头结点
	while (phead) {
		printf("%d->", phead->data);
		phead = phead->next;
	}
	printf("NULL\n");
}

尾删

void shpoptail(slnode** pphead) {
	slnode* cur = *pphead;
	slnode* pre = *pphead;
	while (cur->next) {//找尾
		pre = cur;
		cur = cur->next;
	}
	pre->next = NULL;
	if ((*pphead)->next) {//如果首结点为空,不用free头结点
		free(cur);
	}
}

2 单向循环链表创建(尾插)带头

slnode* creatrnode(int x, slnode*head) {
	slnode* newnode = (slnode*)malloc(sizeof(slnode));
	newnode->data = x;
	newnode->next = head;
	return newnode;
}
void srpushtail(slnode** pphead) {
	slnode* head = creatnode(1);//设置头结点next为空
	*pphead = head;
	slnode* cur = head;//用cur指向新结点
	int x;
	scanf("%d", &x);
	slnode* newnode = creatrnode(x, head);//新结点next指向头结点
	cur->next = newnode;
}
void srprint(slnode* phead) {
	slnode* cur = phead->next;//让头结点不改变
	
	while (phead !=cur) {
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

3双向链表(带头)

sdnode* creatdnode(int x,sdnode* cur) {
	sdnode* newnode = (sdnode*)malloc(sizeof(sdnode));
	newnode->next = NULL;
	newnode->data = x;
	newnode->pre = cur;
	return newnode;
}
void sdprint(sdnode* phead) {
	phead = phead->next;
	while (phead) {
		printf("%d->", phead->data);
		phead = phead->next;
	}
	printf("NULL\n");
}
void sdpush(sdnode** pphead){
	
	sdnode* head=(sdnode*)malloc(sizeof(sdnode));//设置头结点
	head->pre = NULL;
	head->next = NULL;
	head->data = 1;
	*pphead = head;
	int x;
	scanf("%d", &x);
	sdnode* cur = head;
	sdnode* newnode = creatdnode(x, cur);
	cur->next = newnode;
	cur = newnode;
}

4双向循环与单向循环类似

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值