22.假定采用带头节点的单链表保存单词,当两个单词有相同的后缀时,
可共享相同的后缀存储空间,例如,“loading”和“being”的存储映像如下图所示。
设str1和str2分别指向两个单词所在单链表的头结点,链表结点结构为
data | next |
请设计一个时间上尽可能高效的算法,找出由str1和str2所指向两个链表共同后缀
的起始位置(如图中字符i所在结点的位置p),要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C或C++或java语言描述算法,关键支出给出注释。
3)说明你所设计算法的时间复杂度。
/*
存在这样一种情况,如果两个单词又相同的后缀,那我们可以将后缀作为公共部分存储,
比如being和loading,其中ing就可以作为公共部分,
现在存在两个链表,含有公共部分,设计一个高效算法找到其公共后缀真实位置。
分析:
我们可以这样想,如果我们单纯的让两条链表的指针同步移动,
那么只有两条链表长度相同时才有可能在公共部分的起始位置相遇,
所以我们应该让它们处于同一起跑线上,故而我们应该让较长的链表先走,
具体走多少,应该是走过两条链表的长度之差。
*/
#include<stdio.h>
#include<stdlib.h>
#include "linkStruct.h"//通过自创建头文件引入结构体,ctrl+鼠标左键即可查看
Link *findCommonSuffix(Link *h1,Link, h2){
Link *p=h1->next,*q=h2->next;
int countP=0,countQ=0,gao;
while(p){//遍历,获取链表长度
countP++;
p=p->next;
}
if(countQ>countP){//让p指针始终指向较长的那一条链表
p=h2->next;
q=h1->next;
gap=countQ-countP;
}
else{
p=h1->next;
q=h2->next;
gap=countP-countQ;
}
while(gap--) p=p->next;//长链表指针先行移动gap位
while(q!=p&&q!=NULL){//当两指针不同或不为NULL时继续向后移动
q=q->next;
p=p->next;
}
return p;
}
int main(){
Link *h1, *h2,*com,*p1,*p2,*start;
Link *createLink(int);
h1=createLink(1);
h2=createLink(1);
com=createLink(1);//公共部分
p1=h1->next;
p2=h2->next;
while(p1->next) p1=p1->next;//到达链尾
while(p2->next) p2=p2->next;
p1->next=com->next;//链接公共部分
p2->next=com->next;
p1=h1->next;
p2=h2->next;
while(p1){//打印链表
printf("%c",p1->data);
p1=p1->next;
}
printf("\n");
while(p2){//打印链表
printf("%c",p2->data);
p2=p2->next;
}
printf("\n");
strat=findCommonSuffix(h1,h2);//寻找公共后缀
printf("%c",start->data);//打印公共后缀起始节点值
return 0;
}