链表交集相关算法题|AB链表公共元素生成链表C|AB链表交集存放于A|连续子序列|相交链表求交点位置(C)

AB链表公共元素生成链表C

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

算法思想

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

cura小于curb,cura指向cura的next

cura等于curb,malloc一个new节点

curc的next指向new

curc指向new

cura和curb往后遍历

void GetCommon(LinkList &A, LinkList &B)
{
	LNode* cura = A->next, *curb = B->next, *curc, *new;
	LinkList C = (LinkList)malloc(sizeof(LNode));
	curc = C;

	while (cura && curb)
	{
		if (cura->data < curb->data)
			cura = cura->next;
		else if (cura->data > curb->data)
			curb = curb->next;
		else
		{
			new = (LNode*)malloc(sizeof(LNode));
			new->data = cura->data;
			curc->next = new;
			curc = new;
			cura = cura->next;
			curb = curb->next;
		}
	}
	curc->next = NULL;
}

一个工作指针cura用来遍历链表A,一个工作指针curb用来遍历链表B,一个工作指针curc用来建立链表C,一个指针new用来创建共同节点的新节点尾插到C链表上

最开始malloc一个C链表的头节点,将curc指向C链表的头节点

cura和curb开始分别遍历链表A和B

当cura小于curb或者curb小于cura时,小的那一个往后遍历一个节点

当cura等于curb时,malloc一个新节点,使其值等于cura或curb,并将其尾插到C链表上

cura和curb继续往后遍历,直到其中一个指针指向NULL

最后将curc指向NULL

AB链表交集存放于A

已知两个链表A和B分别表示两个集合,其元素递增排列,编制函数,求A与B的交集,并存放于A链表中

算法思想

采用归并的思想,设置两个工作指针cura和curb,对两个链表进行归并扫描,只有同时出现在两集合中的元素才链接到结果表中且仅保留一个,其他的节点全部释放。当一个链表遍历完毕后,释放另一个表中剩下的全部节点

cura小于curb,删除cura

用del指向cura,cura指向cura的next

free掉del

cura等于curb

curc的next指向cura,curc指向cura,cura指向cura的next

del指向curb,curb指向curb的next

free掉del

LinkList Union(LinkList &La, LinkList &Lb)
{
	LNode* cura = La->next;
	LNode* curb = Lb->next;
	LNode* curc = La;
	LNode* del;

	while (cura && curb)
	{
		if (cura->data == curb->data)
		{
			curc->next = cura;
			curc = cura;
			cura = cura->next;
			del = curb;
			curb = curb->next;
			free(del);
		}
		else if (cura->data < curb->data)
		{
			del = cura;
			cura = cura->next;
			free(del);
		}
		else
		{
			del = curb;
			curb = curb->next;
			free(del);
		}
	}
	while (cura)
	{
		del = cura;
		cura = cura->next;
		free(del);
	}
	while (curb)
	{
		del = curb;
		curb = curb->next;
		free(del);
	}
	curc->next = NULL;
	free(Lb);
	return La;
}

cura指针用来遍历链表A,curb用来遍历链表B,curc来指向归并的结果的表头位置,题目要求归并到链表A,所以curc指向La

指针del指向要删除的节点

cura和curb分别从链表A和B的第一个节点开始遍历,其中一个链表遍历结束时,循环结束

当cura等于curb,将cura尾插到curc后面,用del指针删除掉curb

当cura小于curb,删除掉cura

当curb小于cura,删除掉curb

当循环结束后,如果cura不指向NULL,表明链表A中还有剩余的元素,全部删除

如果curb不指向NULL,表明链表B中还有剩余的元素,全部删除

最后将curc的next指向NULL

删除掉链表B的头节点Lb

返回链表A的头节点La

连续子序列

两个整数序列 A = a 1 , a 2 , a 3 , ... , a m A=a_{1},a_{2},a_{3},\dots,a_{m} A=a1,a2,a3,...,am和 B = b 1 , b 2 , b 3 , ... , b n B=b_{1},b_{2},b_{3},\dots,b_{n} B=b1,b2,b3,...,bn已经存入两个单链表中,设计一个算法,判断序列B是否是序列A的连续子序列

算法思想

因为两个整数序列已存入两个链表中,操作从两个链表的第一个节点开始,若对应数据相等,则后移指针;若对应数据不相等,则A链表从上次开始比较节点的后继开始,B链表仍从第一个节点开始比较,直到B链表到尾表示匹配成功。

A链表到尾而B链表未到尾白哦是失败

操作中应该记住A链表每次开始的节点,以便下次匹配好从其后继开始

cura等于curb,往后遍历

cura不等于curb

prev指向prev的next,cura等于prev,curb指向B

cura不等于curb

cura等于cura,继续遍历

bool Pattern (LinkList &A, LinkList &B)
{
	LNode* cura = A;
	LNode* prev = cura;
	LNode* curb = B;

	while (cura && curb)
	{
		if (cura->data == curb->data)
		{
			cura = cura->next;
			curb = curb->next;
		}
		else
		{
			prev = prev->next;
			cura = prev;
			curb = B;
		}
	}
	if (curb == NULL)
		return true;
	else
		return false;
}

用cura指针来遍历链表A,用cur指针来遍历链表B,用prev指针保存上一次A链表比较的节点,下一轮直接从prev的后继节点开始

cura和curb开始同时遍历,当cura和curb其中一个指向NULL,循环结束

当cura等于curb时,继续往后比较链表A和链表B的剩余部分

当cura不等于curb时

prev指向prev的next,也就是A链表开始比较的节点往后走一个

cura指向prev,curb重新指向链表B的表头,开始新的一轮比较

循环结束后,如果curb指向NULL,表示链表B的curb都等于对应的cura,链表B是链表A的连续子序列

否则就不是

相交链表求交点位置

假定采用带头节点的单链表保存单词,当两个单词有相同后缀时,可共享相同的后缀存储空间

如loading和being

设str1和str2分别指向两个单词所在单链表的头节点

设计一个算法,找出由str1和str2所指向两个链表共同后缀的起始位置,也就是两个链表的交点

算法思想

顺序遍历两个链表到尾节点时,不能保证两个链表同时达到尾节点

假设一个链表比另一个链表长k个节点,现在长链表上遍历k个节点

之后同步遍历两个链表,这样就能保证它们同时达到最后节点

这时候每次遍历两两比较两个链表的节点,如果两个遍历的指针相等,就表示两个链表相交,第一个相等的节点就是交点

  1. 分别求出str1和str2所指的两个链表的长度m和n
  2. 将两个链表以表尾对齐:两个指针分别指向str1和str2的头节点,长的链表先走k个节点,也就是走到第 ∣ m − n ∣ + 1 |m-n|+1 ∣m−n∣+1个节点,
  3. 之后两个指针同步往后遍历,判断它们是否指向同一个节点

str1,走m-n步,也就是1步

开始同时遍历

直到cur1和cur2指向同一个节点为止

typedef struct Node
{
	char data;
	struct Node* next;
}SNode;

int ListLen (SNode* head)
{
	int len = 0;
	while (head->next)
	{
		len++;
		head = head->next;
	}
	return len;
}

SNode* findList(SNode* str1, SNode* str2)
{
	int m, n;
	SNode* cur1, *cur2;
	m = ListLen(str1);             //求str1的长度
	n = ListLen(str2);             //求str2的长度
	for (cur1 = str1; m > n; m--)  //若m>n,使cur1后移m-n步
		cur1 = cur1->next;
	for (cur2 = str2; m < n; n--)  //若n>m,使cur2后移n-m步
		cur2 = cur2->next;
	// 查找交点
	while (cur1->next && cur1->next != cur2->next)
	{
		//两个指针同步向后移动
		cur1 = cur1->next;
		cur2 = cur2->next;
	}
	return cur1->next;             //返回相交链表的交点
}
相关推荐
pianmian12 分钟前
python数据结构基础(7)
数据结构·算法
偷心编程3 小时前
双向链表专题
数据结构
香菜大丸3 小时前
链表的归并排序
数据结构·算法·链表
jrrz08283 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
@小博的博客3 小时前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习
南宫生4 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
泉崎5 小时前
11.7比赛总结
数据结构·算法
你好helloworld5 小时前
滑动窗口最大值
数据结构·算法·leetcode
JSU_曾是此间年少7 小时前
数据结构——线性表与链表
数据结构·c++·算法