带头结点的单链表中,删除与x值相同的结点

在带头结点的单链表L中,删除所有值为x的结点,并释放其空间,假设值为x的结点不唯一,试编写算法以实现上述操作。


 思路:两个指针一次遍历,用p从头到尾扫描单链表,pre指向*p结点的前驱(因为删除一个结点,首先得知道它的前驱结点的位置)。若p所指结点的值为x,则删除,并让p移向它的下一结点,否则让pre和p指针同时后移一个结点。

相关代码:

void del_x(Linklist *&L,ElemType x)
{
    Linklist *p=L->next,*pre=L,*q;	
	//分别定义了结构体指针变量p,以及指向它的前驱的指针变量pre,还有用来临时存放要删除的结点的指针变量q 
    while(p!=NULL){	
        //p不为NULL则为真,用于遍历整个链表,这里也可以直接写"p"表示非0则为真,达到同样的效果。注意这里不能填p->next!=NULL,这样的话最后一个结点会遍历不到
    	if(p->data==x)	
    	    {
    		q=p;	//q临时存放要删除的结点 
    		p=p->next;
    		pre->next=p;
    		free(q);	//这三行为标准的删除语句 
	    }
		else{
			pre=p;
			p=p->next;	//pre与p指针同时向后移一位 
		    }
	}
}

 试编写在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点是唯一的)

 总的原理和上面删除与x值相同的结点差不多,定义一个指针p,和它的前驱指针pre,p还是遍历整个链表,另外还有用来存放它们最小值结点的两个指针,分别为minpre和minp。

相关算法:

Linklist del_Min(Linklist *&L,ElemType x)
{
    Linklist *p=L->next,*pre=L,*q;	
	//分别定义了结构体指针变量p,以及指向它的前驱的指针变量pre。这两个指针用于比较、遍历 
	Linklist *minpre=pre,*minp=p; 
	//分别用来存放pre的值,与最小值minp,这两个智者用于存放最小值的结点以及最小值结点的前驱结点 
    while(p!=NULL){	
        //p不为NULL则为真,用于遍历整个链表,这里也可以直接写"p"表示非0则为真,达到同样的效果。注意这里不能填p->next!=NULL,这样的话最后一个结点会遍历不到
    	if(p->data<minp->data)	
    	    {
    	    	minp=p;	//让minp指向最小值的结点 
				minpre=pre;	//minpre始终指向最小值结点的前一个结点。  	
	    }
			pre=p;
			p=p->next;	//pre与p指针同时向后移一位 
	}
	minpre->next=minp->next;
	free(minp);
	return L;
}

试编写算法将带头结点的单链表就地逆置 ,所谓就地逆置是指辅助空间复杂度为O(1)

第一种方法为直接把链表的指针反过来指向,将第一个结点的next域置空,然后再将头指针指向原本链表的最后一个结点。

相关代码: 

#include <stdio.h>
Linklist Reverse_1(Linklist *&L)
{
	Linklist *pre,*p=L->next,*r=p->next;
	p->next=NULL;	//处理组开始的结点,将它的next域置空,变成逆置链表的尾结点。 
	while(p!=NULL)	//p依旧为遍历单链表 
	{
		pre=p;	//依次遍历 
		p=r;
		r=r->next;
		p->next=pre;	//指针反置,后一个指向前一个结点 
	 } 
	L->next=p;	//将头结点指向原本链表最后一个结点 
	return L;
	
 } 

第二种方法则是使用头插法,首先将第一个结点的next域置为空,然后后面的结点依次连接到头结点后面(注意,后面的每个结点都是连接到头结点),并且后面连接好之前插好的结点。 

#include <stdio.h>
Linklist Reverse_2(Linklist *&L)
{
	Linklist *pre,*p=L->next;
	L->next=NULL;	//第一次循环会将第一个结点变成尾结点,会将L->next赋值给尾结点的指针域,即赋值为空 
	while(p!=NULL)	//p依旧为遍历单链表 
	{
		pre=p;	//将p所指向的结点让pre也指向 
		p=p->next;	 
		pre->next=L->next;	//下面这两步是常规的插入操作,先连后断,现将pre的next域指向L的next域所指向的结点 
		L->next=pre;	//将L的next域指向pre,两者不可调换位置,否则会断链。 
	 } 
	return L;
	
 } 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值