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个节点
之后同步遍历两个链表,这样就能保证它们同时达到最后节点
这时候每次遍历两两比较两个链表的节点,如果两个遍历的指针相等,就表示两个链表相交,第一个相等的节点就是交点
- 分别求出str1和str2所指的两个链表的长度m和n
- 将两个链表以表尾对齐:两个指针分别指向str1和str2的头节点,长的链表先走k个节点,也就是走到第 ∣ m − n ∣ + 1 |m-n|+1 ∣m−n∣+1个节点,
- 之后两个指针同步往后遍历,判断它们是否指向同一个节点
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; //返回相交链表的交点
}