AB链表公共元素生成链表C
设A和B是两个单链表(带头节点),其中元素递增有序。设计一个算法从A和B中的公共元素产生单链表C,要求不破坏A、B的节点
算法思想
表A,B都有序,可从第一个元素起依次比较A、B两表的元素,若元素值不等,则值小的值往后移,若元素值相等,则创建一个值等于两节点的元素值的新节点,使用尾插法插入到新的链表中,并将两个原表指针后移一位,直到其中一个链表遍历到表尾
![![[Pasted image 20241104203653.png]]](https://i-blog.csdnimg.cn/direct/fea0ed96e5924278b496de1873367e7c.png)
cura小于curb,cura指向cura的next
![![[Pasted image 20241104203707.png]]](https://i-blog.csdnimg.cn/direct/3d0d9b08af564dfcb8fe416bbbca35a3.png)
cura等于curb,malloc一个new节点
![![[Pasted image 20241104203725.png]]](https://i-blog.csdnimg.cn/direct/d37dbb37023741fb91c2182b6d59e5b1.png)
curc的next指向new
![![[Pasted image 20241104203747.png]]](https://i-blog.csdnimg.cn/direct/10e10a1d70cc4ba4995099ed56f02ed2.png)
curc指向new
![![[Pasted image 20241104203811.png]]](https://i-blog.csdnimg.cn/direct/d3e01a2948274441ab3b4bd678784e86.png)
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,对两个链表进行归并扫描,只有同时出现在两集合中的元素才链接到结果表中且仅保留一个,其他的节点全部释放。当一个链表遍历完毕后,释放另一个表中剩下的全部节点
![![[Pasted image 20241104210025.png]]](https://i-blog.csdnimg.cn/direct/e2d750ed8f514027b5036851e13c0895.png)
cura小于curb,删除cura
用del指向cura,cura指向cura的next
![![[Pasted image 20241104210120.png]]](https://i-blog.csdnimg.cn/direct/cc18debd27eb4d69a7d5cd4f93cdf2aa.png)
free掉del
![![[Pasted image 20241104210148.png]]](https://i-blog.csdnimg.cn/direct/6320e790e57f4298a90b9d2466aa29f0.png)
cura等于curb
curc的next指向cura,curc指向cura,cura指向cura的next
![![[Pasted image 20241104210253.png]]](https://i-blog.csdnimg.cn/direct/3d11ba009423425d8a3eeb6834bfd28a.png)
del指向curb,curb指向curb的next
![![[Pasted image 20241104210323.png]]](https://i-blog.csdnimg.cn/direct/027fe89c075a4ca38d9c55bba2e51190.png)
free掉del
![![[Pasted image 20241104210336.png]]](https://i-blog.csdnimg.cn/direct/106b97fcd14f455794633d94e0bb20bc.png)
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=a1,a2,a3,…,amA=a_{1},a_{2},a_{3},\dots,a_{m}A=a1,a2,a3,…,am和B=b1,b2,b3,…,bnB=b_{1},b_{2},b_{3},\dots,b_{n}B=b1,b2,b3,…,bn已经存入两个单链表中,设计一个算法,判断序列B是否是序列A的连续子序列
算法思想
因为两个整数序列已存入两个链表中,操作从两个链表的第一个节点开始,若对应数据相等,则后移指针;若对应数据不相等,则A链表从上次开始比较节点的后继开始,B链表仍从第一个节点开始比较,直到B链表到尾表示匹配成功。
A链表到尾而B链表未到尾白哦是失败
操作中应该记住A链表每次开始的节点,以便下次匹配好从其后继开始
![![[Pasted image 20241104211850.png]]](https://i-blog.csdnimg.cn/direct/5365b37c9af141a9b846c81afe69748f.png)
cura等于curb,往后遍历
![![[Pasted image 20241104211921.png]]](https://i-blog.csdnimg.cn/direct/45fd7ca4813e4af497a5afc787d44254.png)
cura不等于curb
prev指向prev的next,cura等于prev,curb指向B
![![[Pasted image 20241104212014.png]]](https://i-blog.csdnimg.cn/direct/c31b790f006645acb7c42b593ecf9459.png)
cura不等于curb
![![[Pasted image 20241104212039.png]]](https://i-blog.csdnimg.cn/direct/95cbe46aa7fe43638fcad475e3ef3b56.png)
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
![![[Pasted image 20241104200916.png]]](https://i-blog.csdnimg.cn/direct/ed191e54b239455e97e1a0291b9bf1f0.png)
设str1和str2分别指向两个单词所在单链表的头节点
设计一个算法,找出由str1和str2所指向两个链表共同后缀的起始位置,也就是两个链表的交点
算法思想
顺序遍历两个链表到尾节点时,不能保证两个链表同时达到尾节点
假设一个链表比另一个链表长k个节点,现在长链表上遍历k个节点
之后同步遍历两个链表,这样就能保证它们同时达到最后节点
这时候每次遍历两两比较两个链表的节点,如果两个遍历的指针相等,就表示两个链表相交,第一个相等的节点就是交点
- 分别求出str1和str2所指的两个链表的长度m和n
- 将两个链表以表尾对齐:两个指针分别指向str1和str2的头节点,长的链表先走k个节点,也就是走到第∣m−n∣+1|m-n|+1∣m−n∣+1个节点,
- 之后两个指针同步往后遍历,判断它们是否指向同一个节点
![![[Pasted image 20241104214225.png]]](https://i-blog.csdnimg.cn/direct/74f29f6b90fc44df9f109090c2542b16.png)
str1,走m-n步,也就是1步
![![[Pasted image 20241104214343.png]]](https://i-blog.csdnimg.cn/direct/76e8759a3d5b408cad526bf6615ae9b1.png)
开始同时遍历
![**![[Pasted image 20241104214412.png]]**](https://i-blog.csdnimg.cn/direct/64e37db42a6746b49b5d7f178be7745c.png)
直到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; //返回相交链表的交点
}

被折叠的 条评论
为什么被折叠?



