6000字长文只为讲解好的数据结构代码题---Day05

数据结构代码题总结

题目01

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

1、解题思路:

  1. 题目的实现分析
  2. 首先是要拆分线性表:
  3. 问题1:如何拆分线性表

针对问题1如何拆分线性表,这里主要采用两种方式进行实现:

第一种:

1. 设置一个常量指针i,使得i = 0;每遍历一个单链表节点,便让i+1,
2. 对于拆分,则对i进行
(i%2==0)进行奇数和偶数判断
3. 若是奇数那么将其拆分进行将节点数值进行拆分到A中
4. 若是偶数则拆分到B链表中,
这里给出相关的理论图进行讲解:

在这里插入图片描述
根据上述图片,进行问题1的解答。

第二种方式:

1. 通过采用首节点开始,进行遍历
2. 只要从第一个节点进行拆分进行A链表那么,第一个节点后面的元素,只要它不是null,也就是要被拆分到B链表中了。

基于上述的两种拆分情况,我们分别讨论,先放一边,
这里进行讨论第二个问题:

问题2:如何实现拆分到B链表的元素的顺序是相反的

答:这里由于B链表的拆分顺序是从bn到b1的,是逆序的,这里就联想到了最为基础的建立单链表的设计思路。

1. 头插法顺序相反
2. 尾插法顺序相同

由于我们B链表是逆序,因此对B链表的操作要以头插法的方式进行,对于A链表的拆分以尾插法的方式进行。
也就是上面问题2的答案。

下面先针对第二种顺序拆分方式进行编写代码:

首先是核心代码:

while(p!= null){
		//按照第二种方式,从第一个元素开始进行拆分,
		//第一个是a1,因此采用尾插法进行插入A链表
		ra->next = p;
		ra = p;//尾插法
		p = p->next;//向后移动p
		if(p != null){//p后面还有元素
			//这里进行头插法进行操作
			/**
			 * 记忆口诀:
			 * 头插法防止断链
			 * 尾插法要留尾部指针为null
			 */
			r = p->next;//保存防止断链
			p->next = rb->next;//头插法建立单链表的过程操作
			rb->next = p;
			p = r;
		}
	}

第二种方式拆分链表完整代码:

//顺序拆分单链表,A顺序尾插法,B顺序头插法
Linklist Create_Linklist(Linklist &hc){
	//初始化节点
	LNode * r;
	LNode * p = hc->next;
	//链表初始化
	A = (Linklist)malloc(sizeof(LNode));
	B = (Linklist)malloc(sizeof(LNode));
	A->next = null;
	LNode * ra = A;
	B->next = null;
	LNode * rb = B;
	//核心操作代码
	while(p!= null){
		//按照第二种方式,从第一个元素开始进行拆分,
		//第一个是a1,因此采用尾插法进行插入A链表
		ra->next = p;
		ra = p;//尾插法
		p = p->next;//向后移动p
		if(p != null){//p后面还有元素
			//这里进行头插法进行操作
			/**
			 * 记忆口诀:
			 * 头插法防止断链
			 * 尾插法要留尾部指针为null
			 */
			r = p->next;//保存防止断链
			p->next = rb->next;//头插法建立单链表的过程操作
			rb->next = p;
			p = r;
		}
	}
	return A;
	return B;
}

结合以上的第二种拆分方式,这里对其进行改进,实现以第一种方式进行操作。添加了i等于0

//顺序拆分单链表,A顺序尾插法,B顺序头插法
Linklist Create_Linklist(Linklist &hc){
	//初始化节点
	LNode * r;
	LNode * p = hc->next;
	int i = 0;
	//链表初始化
	A = (Linklist)malloc(sizeof(LNode));
	B = (Linklist)malloc(sizeof(LNode));
	A->next = null;
	LNode * ra = A;
	B->next = null;
	LNode * rb = B;
	//核心操作代码
	while(p!= null){
		//按照第二种方式,从第一个元素开始进行拆分,
		//第一个是a1,因此采用尾插法进行插入A链表
		if(i %2 == 0){
			ra->next = p;
			ra = p;//尾插法
			p = p->next;//向后移动p
			i++;
		}else{//奇数顶点
			//这里进行头插法进行操作
			/**
			 * 记忆口诀:
			 * 头插法防止断链
			 * 尾插法要留尾部指针为null
			 */
			r = p->next;//保存防止断链
			p->next = rb->next;//头插法建立单链表的过程操作
			rb->next = p;
			p = r;
			i++;
		}
	}
	return A;
	return B;
}

题目02

在一个递增有序的线性表中,有数值相同的元素存在,若存储方式为单链表,设计算法去掉数值相同的元素,使得表中不再存在相同的元素。这里举例{7,10,10,21,30,42,42,42,51,70}变化为{7,10,21,30,42,51,70}

1、题目分析:

  1. 要删除相同数值的元素的步骤一般为:
  2. 先查找相同的元素
  3. 然后删除

首先是要查找相同元素的方法,则是需要通过指针进行,对于指针的数量应该是2个,一个pre作为前驱,一个操作指针p,其实现图如下:
在这里插入图片描述
结合图解得到的算法设计思路如下:
遍历单链表,设置一个pre指针,指向头节点的后继,p指针指向pre的后继,进行循环,检测pre的数据与p的数据是否相等,相等则执行删除操作,不相等则,继续向后移动。

其核心实现代码如下:

	//核心代码
	while(p != null){
		if(pre->data == p->data){//找到相同元素
			//执行删除
			pre->next = p->next;
			free(p);//释放内存
			//重新定义p
			p = pre->next;
		}else{
			//若不相等
			pre = p;//先操作pre,pre 后移,p再后移
			p = p->next;
		}
	}

完整代码:

//需要对其进行删除,必须要加上&符号
void Delete_SameExample(Linklist &L){
	LNode * pre = L->next;
	LNode * p = pre->next;//定义前驱指针和操作指针
	//核心代码
	while(p != null){
		if(pre->data == p->data){//找到相同元素
			//执行删除
			pre->next = p->next;
			free(p);//释放内存
			//重新定义p
			p = pre->next;
		}else{
			//若不相等
			pre = p;//先操作pre,pre 后移,p再后移
			p = p->next;
		}
	}
}

题目03

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

题目分析:
1、两个递增的单链表->>>>>递减的单链表
2、同时由于利用原来的两个单链表的节点存放归并后的单链表表示不可以再申请一个类似于数组的数据结构进行存放节点数据,但是设置一个合并链表。其实现的思路图如下:

在这里插入图片描述

结合以上的图解
其中实现的思路主要是

  1. 对p和q的数据进行比较,较小的数据节点以头插法的方式再合并链表上进行插入,这样对于操作的递减次序进行实现。
  2. 对于A和B链表中的多余数据直接添加入合并链表,(由于是递增次序)

其实现的核心代码:

A->next = null;//头插法的设计第一步需要对其进行初始化
	//A链表作为初始化的合并链表
	while(p!= null && q != null){
		if(p->data < q->data){
		//p小于,对A进行头插法
			r = p->next;
			p->next = A->next;
			A->next = p;
			p = r;
	}else{
			r = q->next;
			q->next = A->next;
			A->next = q;
			q = r;
		}
	}
	while(q != null){//b有剩余
			r = q->next;
			q->next = A->next;
			A->next = q;
			q = r;
	}
	while(p != null){//A剩余
		    r = p->next;
			p->next = A->next;
			A->next = p;
			p = r;
	}

全部代码:

Linklist Merge_list(Linklist &A,Listlink &B){
	LNode * p = A->next;
	LNode * q = B->next;
	LNode * r ;//保存后继
	A->next = null;//头插法的设计第一步需要对其进行初始化
	//A链表作为初始化的合并链表
	while(p!= null && q != null){
		if(p->data < q->data){
		//p小于,对A进行头插法
			r = p->next;
			p->next = A->next;
			A->next = p;
			p = r;
	}else{
			r = q->next;
			q->next = A->next;
			A->next = q;
			q = r;
		}
	}
	while(q != null){//b有剩余
			r = q->next;
			q->next = A->next;
			A->next = q;
			q = r;
	}
	while(p != null){//A剩余
		    r = p->next;
			p->next = A->next;
			A->next = p;
			p = r;
	}
	return A;

}

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

题目分析:
如下图所示对当前的题目中的实现要求为:

  1. 要求不破坏A和B的节点表示不可以再A和B链表上进行操作,只能扫描
  2. 需要对其剩余节点进行操作,
  3. 如果存在长链表,由于其为递增序列,
  4. 因此在一个链表遍历结束后,长链表还没有遍历结束,但是当前是绝对不会存在公共节点的!!!!!!!!
  5. 因此节点剩余的情况不需要考虑了!!!

思路图:
在这里插入图片描述
对以上的思路图进行解析:

  1. 算法的执行首先需要申请一个存储空间C
  2. 设置两个扫描指针p和q,进行遍历链表,进行比较,哪个数值小,哪个指针向后移动
  3. 当p和q的数据相等时,需要开启一个新的节点,并将其进行赋值采用尾插法的方式进行插入C链表中,然后p和q指针同时向后移动
  4. 若A比B长,由于是递增序列, 但是这个时候B已经遍历结束,不会再出现新的公共节点,所以对剩余的节点不做处理。

其实现的核心代码如下:

	while(p != NULL && q != NULL ){
		if(p->data < q->data){
			//a的数据小,后移
			p = p->next;
		}else if(p->data > q->data){
			q = q->next;//B后移
		}else{//找到了公共节点
			//开辟新的节点
			LNode* s = (LNode*)malloc(sizeof(LNode));
			s->data = p->data;//为节点赋值
			r->next = s;
			r = s;//尾插法进行建立单链表
			p = p->next;//继续操作,同时向后移动
			q = q->next;
		}
	}

全部解答代码:

Linklist Create_LinklistbyHigh(Linklist &A,Linklist &B){
	//初始化节点
	LNode * p = A->next;
	LNode * q = B->next;
	C = (Linklist)malloc(sizeof(LNode));//设置开辟新的链表
	C>next = null
	LNode * r = C;
	while(p != null && q != null){
		if(p->data < q->data){
			//a的数据小,后移
			p = p->next;
		}else if(p->data > q->data){
			q = q->next;//B后移
		}else{//找到了公共节点
			//开辟新的节点
			LNode* s = (LNode*)malloc(sizeof(LNode));
			s->data = p->data;//为节点赋值
			r->next = s;
			r = s;//尾插法进行建立单链表
			p = p->next;//继续操作,同时向后移动
			q = q->next;
		}
	}
	//尾插法的重中之重!!!!!!!!
	//必须设计尾部指针
	r->next = null;
	return C;
}

6000字长文只为解答数据结构 算法代码,觉得好的话还请大佬点赞支持!!!!

注:

个人代码问题或需要程序编写辅导服务等问题请加闲鱼【代码无bug】
或点击下面链接跳转闲鱼进行咨询

闲鱼链接

在这里插入图片描述

  • 46
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值