单链表的增删查改

目录

尾插

头插

 头删

尾删

 查改

查头插

查尾插

查删

查后删


尾插

思路:单链表的创建—从零开始_哔哩哔哩_bilibili

1.创建指针变量tail,让tail=head。

2.tail遍历链表直到为NULL,即找到了尾节点

3.创建一个新节点newnode

4.让tail的next指向newnode完成连接

5.把newnode给给tail,让tail跳到newnode头上。


#include<assert.h>


//定义一个结构体,一个链表中的节点就是一个结构体,每个节点里面都存有data和next,next存放着下个节点的地址
typedef struct node
{
	int data;
	struct node* next;
}node;




//尾插函数
node* sltpushback(struct node* head)
{
    struct node* tail = head;
    while(tail->next!=NULL)
    {
        tail = tail->next;
    }
    for (int i = 1; i <= 3; i++)
    {
        struct node* temp = (struct node*)malloc(sizeof(struct node));
if(temp==NULL)//判断是否开辟成功
{
perror("malloc fail");
}
        temp->data = i;
        temp->next = NULL;
        
        tail->next = temp;
        tail = temp;

    }
    return head;
}

node* sltprint(node* head)
{

	head = head->next;
	while (head!=NULL)
	{
		printf("%d->", head->data);
		head = head->next;
	}
	printf("NULL");
	return head;
}

int main()
{
	struct node* head;
	 head =(node*)malloc(sizeof(node));
if(head==NULL)//判断是否开辟成功
{
perror("malloc fail");
}
	head->next = NULL;

	head= sltpushfront(head);

	 sltprint(head);
return 0;
}

 



 

头插

数据结构入门——头插法创建链表_本题目要求以头插法建立单链表。_skchendj的博客-CSDN博客

只需要在尾插的基础上改一下就可以了。

node* SLTpushFront(node* head)
{
 
	node* tail = head;
for (int i = 1; i <= 10; i++)
	{
node* tmp = (node*)malloc(sizeof(node));
if(tmp==NULL)//判断是否开辟成功
{
perror("malloc fail");
}
tmp->data = i;
tmp->next = head->next;//用新节点指向原来的头节点
head->next = tmp;//把头指针指向新节点

	}
return head;
}

 

 也可以改简洁一点代码,既然尾插要开辟新节点,头插又要开辟新节点,干脆写个开辟新节点的函数,在头插尾插里直接调用就可以了。

void* Creatnode()
{
	node* newnode;
	for (int i = 1; i <= 10; i++)
	{
newnode = (node*)malloc(sizeof(node));
if(newnode==NULL)//判断一下是否开辟成功
{
perror("malloc fail");
}
newnode ->data = i;
	newnode->next = NULL;
	}
	
	return newnode;

}




node* SLTpushFront(node* head)
{
 
	node* tail = head;
for (int i = 1; i <= 10; i++)
	{
node* tmp=Creat();
tmp->next = head->next;//用新节点指向原来的头节点
head->next = tmp;//把头指针指向新节点

	}
return head;
}

 头删

思路:把head赋值给tail然后head跳到下个节点,然后让tail的next置为空,这样第一个节点就连接不到下个节点了

 最后把tailfree一下就把第一个节点free掉了。

 代码:

node* SLTPopfront(node* head)
{
assert(head);//断言一下,如果,没有一个节点,那还头删什么。
if(head->next)
{
return NULL;
}
else//如果多个节点正常操作

{
	node* tail = head;
		head = head->next;
		tail->next = NULL;

	free(tail);
}
	return head;
}

 

尾删

 思路:一个src一个tail,把src放head的位置,tail放src的下一节点。让tail和src同步走,但是tail比src快一个节点,当tail走到NULL走完的时候,src刚好走到第二个节点上。

 

 

然后把src的next置为空,这样就把链表与最后一个节点的连接断开了

再把tail free掉。

 

 代码:


node* SLTPopback(node* head)
{
	assert(head);//断言一下,如果头节点为空就删不了什么,就报错
	if (head->next == NULL)//如果只有头节点, 那怎么删呢,直接返回空,让头节点变为空就把头节点删了
	{
		return NULL;
	}
	else //否则就是多节点,正常操作就行
{
node* src = head;
	node* tail = src->next;
	while (tail->next)
	{
		tail = tail->next;
		src = src->next;
	}
	src->next = NULL;
	tail = NULL;
	free(tail);
	}
	return head;//最后要把链表的头结点返回去,不然找不到链表的头结点
}

查改pops

思路:输入一个要查找的值x,然后把head复制给cur,让cur从头节点位置开始找,如果找到了就把cur返回去。如果没找到就让cur继续往下走,直到走到NULL遍历完为止,还没找到就返回NULL;

node* SLTFind(node* head,int x)
{
	node* cur = head;

	while(cur)
		{
	
if (cur->data == x)
{
	return cur;

	}	
cur = cur->next;

		}
	again:
	return NULL;

}

或者这个:

node* SLTFind(node* head,int x)
{
	node* cur = head;

	while(cur)
{
	
if (cur->data == x)
{
	goto again;

}	
cur = cur->next;

}
	again:
	return cur;

}

node* re=Find(head,x);

找到这个数后用指针re接收,就可以通过修改re来达到改变查找的数的目的了。

在pops前插入

假如有一串数字

 现在我们想在3前面插入一个12

1.re是查找函数的返回值,我们要查找3,re就等于3.

2.然后开辟一个新节点,给新节点复制12.

3. 让tail从头节点的位置开始找re,如果找到re就停止,把tail的next连接newnode,newnode的next连接re,这样就完成了在re面前插入12。


//创建新节点,给新节点初始化+赋值12
void* Creatnode()
{
	node* newnode;
	for (int i = 11; i <= 12; i++)
	{
newnode = (node*)malloc(sizeof(node));
if(newnode==NULL)
{
perror("malloc fail");
}
newnode ->data = i;
	newnode->next = NULL;
	}
	
	return newnode;

}










node* SLTFrontre(node* head,node* re)
{
assert(head);//因为要靠tail从头节点去遍历到re的位置,如果头节点为NULL就不行了
assert(re);//re也不能为空,不然都查不到re怎么插在re前面。
	node* newnode = Creatnode();
	node* tail = head;
	while (tail->next!=re)//如果tail找不到re就一直往下找
	{
		tail = tail->next;
	}
	tail->next = newnode;
	newnode->next = re;

	return head;

}

但是这个代码实际上是有缺陷的。

假如我们要查找的数在头节点上,用这个代码怎么在头节点前插入呢

比如我们要查10,在10前面插入一个12

 我们加一个条件:如果要查的数==头节点,就把新节点头插在头节点前。

	if (head == re)
	{
		newnode=sltpushfront(head);
	}

在pops后面插入

思路:把re指向的下一个节点给成newnode所指向

 然后再把re指向newnode。

void* SLTBackre( node* re)
{
	assert(re);//不需要tail来遍历了,也就不用头节点了,不用断言head了
	node* newnode = Creatnode();
	
	newnode->next=re->next;
	re->next = newnode;

	return newnode;
	

}

删除pops

思路:

1.如果re在头节点,引用头删函数

2.其他情况,先找到re前面的节点

3.然后把re连接的下一个节点给成re上一个节点所连

4.free(re)

void* SLTPopre(node* head,node* re)
{
	assert(head);
	assert(re);
	if(re == head)
	{
		re=SLTPopBack(head);
	}
	else
	{
		node* prev = head;

		while (prev->next != re)
		{
		prev=prev->next;
		}
		prev->next=re->next;
		free(re);
	}
	return head;
}

删除最后一个节点

比如我们想把re后面这个节点删了

1.把要删除的这个节点命名为Next,Next=re->next;

2.让Next所指向的下一节点给re(即便下一节点为NULL):re->next=Next->next;

3.free(Next)

void* SLTEraseRe(node* re)
{
	node* Next = re->next;
	re->next = Next->next;
	free(Next);
	return re;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孙鹏宇.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值