2.3线性表的链式表示(1)

1、设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点
在这里插入图片描述

void Del_X_3(Linklist &L,ElemType x){
	LNode *p;	//p指向待删除结点 
	if(L==NULL)	//递归出口	
		return;
	if(L->data==x){	// 若L所指结点的值为x 
		p=L;		//删除*L,并让L指向下一结点 
		L=L->next;
		free(p);
		Del_X_3(L,x);	//递归调用 
	}
	else				//若L所指结点的值不为x 
		Del_X_3(L->next,x);//递归调用 
} 

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

void Del_X_1(Linklist &L,ElemType x){
	LNode *p=L->next,*pre=L,*q;//置p和pre的初始值 
	while(p!=NULL){
		if(p->data==x){
			q=p;			//q指向该节点 
			p=p->next;
			pre->next=p;	//删除*q结点 
			free(q);		//释放*q结点的空间 
		}
		else{				//否则pre和p同步后移 
			pre=p;
			p=p->next; 
		}
	}
} 

在这里插入图片描述

void Del_X_1(Linklist &L,ElemType x){
	LNode *p=L->next,*r=L,*q;//r指向尾结点,其初值为头结点 
	while(p!=NULL){
		if(p->data!=x){	//*p结点值不为x时将其链接到L尾部 
			r->next=p;
			r=p;
			p=p->next;	//继续扫描 
		}
		else{			//*p结点值为x时将其释放 
			q=p;		 
			p=p->next;	//继续扫描 
			free(q);	//释放空间 
		}
	}
	r->next=NULL;		//插入结束后置尾节点指针为NULL 
} 

3、设L是带头结点的单链表,编写算法实现从尾到头反向输出每个结点的值。
在这里插入图片描述

void Reverse(Linklist L){
	if(L->next!=NULL){
		Reverse(L->next);
	}
	if(L!=NULL) print(L->data);
} 

4、试编写在带头结点的单链表L中删除一个最小值结点的高效算法。
在这里插入图片描述

LinkList Delete_Min(LinkList &L){
	LNode *pre=L,*p=pre->next;//p为工作指针,pre指向其前驱 
	LNode *minpre=pre,*minp=p;//保存最小值结点及其前驱 
	while(p!=NULL){
		if(p->data<minp->data){
			minp=p;			//找到比之前找到的最小值结点更小的结点 
			minpre=pre;
		}
		pre=p;		//继续扫描下一个结点 
		p=p->next;
	}
	minpre->next=minp->next;	//删除最小值结点 
	free(minp);
	return L;
}

5、试编写算法将带头结点的单链表就地逆置
在这里插入图片描述

LinkList Reverse1(LinkList L){
	LNode *p,*r;	//p为工作指针,r为p的后继,以防断裂 
	p=L->next;	//从第一个元素结点开始 
	L->next=NULL;//先将头结点L的next域置为NULL 
	while(p!=NULL){//依次将元素结点摘下 
		r=p->next;//暂存p的后继 
		p->next=L->next;//将p结点插入到头结点之后 
		L->next=p;
		p=r;
	} 
}

在这里插入图片描述

LinkList Reverse1(LinkList L){
	LNode *pre,*p=L->next,*r=p->next;
	p->next=NULL;//处理第一个节点 
	while(r!=NULL){//r为空,则说明p为最后一个结点 
		pre=p;	//依次继续遍历 
		p=r;	 
		p->next=pre;	//指针反转 
	}
	L->next=p;	//处理最后一个结点 
	return L; 
}

6、有一个带头结点的单链表L,设计一个算法使其元素递增有序。
在这里插入图片描述

void Sort(LinkList &L){
//本算法实现将单链表L的结点重排,使其递增有序 
	LNode *p=L->next,*pre;
	LNode *r=p->next;//r保持*p后继节点指针,以保证不断链 
	p->next==NULL;//构造只含一个数据结点的有序表 
	p=r;
	while(p!=NULL){
		r=p->next;	//保存*p的后继结点指针 
		pre=L;
		while(pre->next!=NULL&&pre->next->data<p->data)
			pre=pre->next;//在有序表中查找插入*p的前驱结点*pre 
		p->next=pre->next;//将*p插入到*pre之后 
		pre->next=p;
		p=r;//扫描原单链表中剩下的结点 
	} 
}

7、设在一个带头结点的单链表中所有元素结点的数据值无序,试编写一个函数,删除表中元素所有介于给定的两个值(作为函数参数给出)之间的元素(若存在 )

void RangeDelete(LinkList &L,int min,int max)
{
	LNode *pr=L,*p=L->link;//p是检测指针,pr是其前驱 
	while(p!=NULL){
		if(p->data>min&&p->data<max){//寻找到被删结点,删除 
			pr->link=p->link;
			free(p);
			p=pr->link;
		}
		else{			//否则继续寻找被删结点 
			pr=p;
			p=p->link;
		}		
	}	
} 

8、给定两个单链表,编写算法找出两个链表的公共结点
在这里插入图片描述

LinkList Search_Commom(LinkList L1,LinkList L2){
//本算法实现在线性时间内找到两个单链表的第一个公共结点 
	int len1=Length(L1),len2=Length(L2);//计算两个链表的表长 
	LinkList longList,shortList;//分别指向表长较长和较短的链表 
	if(len1>len2){				//L1表长较长 
		longList=L1->next;shortList=L2->next;
		dist=len1-len2;			//表长之差 
	}
	else{				//L2表长较长 
		longList=L2->next;shortList=L1->next;
		dist=len2-len1;	//表长之差 
	}
	while(dist--){	//表长的链表先遍历到第dist个结点,然后同步 
		longList=longList->next;
	}
	while(longList!=NULL){	//同步寻找共同结点 
		if(longList==shortList)//找到第一个公共结点 
			return longList;
		else{			//继续同步寻找 
			longList=longList->next;
			shortList=shortList->next;
		}
	}
	return NULL;
	
}

9、给定一个带表头结点的单链表,设head为头指针,结点结构为(data,next),data为整型元素,next为指针,试写出算法:按递增次序输出单链表各节点的数据元素,并释放结点所占存储空间。(不允许使用数组作为辅助空间)

在这里插入图片描述

void Min_Delte(LinkList &head)
{//head是带头结点的单链表的头指针,本算法按递增顺序输出单链表中的数据元素 
	while(head->next!=NULL){//循环到仅剩头结点 
		pre=head;	//pre为元素最小值结点的前驱结点的指针 
		p=pre->next;//p为工作指针 
		while(p->next!=NULL){
			if(p->next->data<pre->next->data)
			pre=p;		//记住当前最小值结点的前驱 
			p=p->next;
		}
		print(pre->next->data);//输出元素最小值结点的数据 
		u=pre->next;	//删除元素值最小的结点,释放结点空间 
		pre->next=u->next;
		free(u);
	}
	free(head);//释放头结点 
}

10、将一个带头节点的单链表A分解为两个带头节点的单链表A和B,使得A表中含有原表中序号为奇数的元素,而B表中含有原表中序号为偶数的元素,且保持其相对顺序不变

void Min_Delte(LinkList &head)
{//head是带头结点的单链表的头指针,本算法按递增顺序输出单链表中的数据元素 
	while(head->next!=NULL){//循环到仅剩头结点 
		pre=head;	//pre为元素最小值结点的前驱结点的指针 
		p=pre->next;//p为工作指针 
		while(p->next!=NULL){
			if(p->next->data<pre->next->data)
			pre=p;		//记住当前最小值结点的前驱 
			p=p->next;
		}
		print(pre->next->data);//输出元素最小值结点的数据 
		u=pre->next;	//删除元素值最小的结点,释放结点空间 
		pre->next=u->next;
		free(u);
	}
	free(head);//释放头结点 
}

11、设C={a1,b1,a2,b2,…,an,bn}为线性表,采用带头节点的hc单链表存放,设计一个就地算法,将其拆分为2个线性表,使得A={a1,a2,…,an},B={bn,…,b2,b1}

LinkList DisCreat(LinkList &A)
{
	LinkList B=(LinkList)malloc(sizeof(LNode));//创建B表表头 
	B->next=NULL;		//B表的初始化 
	LNode *p=A->next,*q;//p为工作指针 
	LNode *ra=A;	//ra始终指向A的尾节点 
	while(p!=NULL){
		ra->next=p;ra=p;	//将*p链到A的表尾 
		p=p->next;
		p->next=B->next;	//头插后,*p将断链,因此q记忆*p的后继 
		B->next=p;		//将*p插入到B的前端 
		p=q;
	} 
	ra->next=NULL;		//A尾结点的next域置空 
	return B;
} 

12、在一个递增有序的线性表中,有数值相同的元素存在。若存储方式为单链表,设计算法去掉数值相同的元素,使表中不再有重复的元素

void Del_Same(Linklist &L){
//L是递增有序的单链表,本算法删除表中数值相同的元素	
	LNode *p=L->next,*q;//p为扫描工作指针 
	if(p==NULL)
		return;
	while(p->next!=NULL){
		q=p->next;	//q指向*p的后继结点 
		if(p->data==q->data){	//找到重复值的结点 
			p->next=q->next;	//释放*q结点 
			free(q);		//释放相同元素值的结点 
		}
		else
			p=p->next;
	}
}

13、假设有2个按元素值递增排列的线性表,均以单链表形式存储。编写算法将这2个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两个单链表的结点存放归并后的单链表

算法思想:两个链表已经按元素值递增次序排序,将其合并时,均从第一个结点起进行比较,将小的结点链入链表中,同时后移工作指针。该问题要求结果链表按元素值递减次序排列,故新链表的建立应采用头插法。比较结束后,可能会有一个链表非空,此时用头插法将剩下的结点依次插入新链表中即可。

void MergeList(LinkList &La,LinkList &Lb){
//合并两个递增有序链表(带头结点),并使合并后的链表递减排列 
	LNode *r,*pa=La->next,*pb=Lb->next;//分别是表La,Lb的工作指针 
	La->next=NULL;//La作为结果链表的头指针,先将结果链表初始化为空 
	while(pa&&pb){//当两链表均不为空时,循环 
		if(pa->data<=pa->data){
			r=pa->next;	//r暂存pa的后继指针 
			pa->next=La->next;
			La->next=pa;//将pa为当前待比较结点 
			pa=r;
		}
		else{
			r=pb->next;	//r暂存pb的后继结点指针 
			pb->next=La->next;
			La->next=pb;//将pb结点链于结果表中,同时逆置 
			pb=r;	//恢复pb当前待比较结点 
		}
		if(pa)
			pb=pa;//通常情况下会剩一个链表非空,处理剩下的部分 
		while(pb){//处理剩下的一个非空链表 
			r=pb->next;//依次插入到La中(头插法) 
			pb->next=La->next;
			La->next=pb;
			pb=r;
		}
		free(Lb);
	} 
}

14、设A和B是两个单链表(带头结点),其中元素递增有序。设计一个算法从A和B中的公共元素产生单链表C,要求不破坏A,B的结点

算法思想:表A、B都有序,可从第一个元素起依次比较A、B两表的元素,若元素值不等,则值小的指针往后移,若元素值相同,则创建一个值等于两结点的元素值的新结点,使用尾插法插入到新的链表中,并将两个原表指针后移一位,直到其中一个链表遍历到表尾

void MergeList(LinkList &La,LinkList &Lb){
//合并两个递增有序链表(带头结点),并使合并后的链表递减排列 
	LNode *r,*pa=La->next,*pb=Lb->next;//分别是表La,Lb的工作指针 
	La->next=NULL;//La作为结果链表的头指针,先将结果链表初始化为空 
	while(pa&&pb){//当两链表均不为空时,循环 
		if(pa->data<=pa->data){
			r=pa->next;	//r暂存pa的后继指针 
			pa->next=La->next;
			La->next=pa;//将pa为当前待比较结点 
			pa=r;
		}
		else{
			r=pb->next;	//r暂存pb的后继结点指针 
			pb->next=La->next;
			La->next=pb;//将pb结点链于结果表中,同时逆置 
			pb=r;	//恢复pb当前待比较结点 
		}
		if(pa)
			pb=pa;//通常情况下会剩一个链表非空,处理剩下的部分 
		while(pb){//处理剩下的一个非空链表 
			r=pb->next;//依次插入到La中(头插法) 
			pb->next=La->next;
			La->next=pb;
			pb=r;
		}
		free(Lb);
	} 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值