考研数据结构(每日一题)
题目:假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,可共享相同的后缀存储空间,例如,“loading”和“being”的存储映像如下图:
设str1和str2分半指向两个单词所在单链表的头结点,链表结点结构为
请设计一个时间上尽可能高效的算法,找出由str1和str2所指向两个链表共同后缀的起始位置(如图中字符i所在结点的位置p)
算法思想:
采用双指针法。用指针p、q分别扫描str1和str2,当p、q指向同一个地址时。即可找到共同后缀的起始位置。
注意:这个题目的含义是现在这种结构已经存在了,让你去判断这个起始位置在哪。而不是说给你两个单词序列,让你判断这个起始位置在哪。
算法详细步骤:
第一步:分别求出str1和str2所指的两个链表的长度m和n
第二步:将两个链表的表尾对齐:令指针p和q分别指向str1和str2的头结点,若m>=n,则p往后走,使p指向链表中第m-n+1个结点;若m<n,使q指向链表中第n-m+1个结点。将p和q所指结点到表尾的长度相等。
第三步:重复将p和q同步向后移动,当p和q指向同一位置时停止
完整代码:
typedef struct Node{ //定义结构体
char data;
struct Node *next;
}SNode;
//求链表长度
int listlen(SNode *head){
int len = 0;
while(head -> next != NULL){
len ++;
head = head -> next;
}
return len;
}
//找出共同后缀的起始地址
SNode* find_add(SNode *str1,SNode *str2){
int m,n;
SNode *p,*q;
m = listlen(str1); //求str1的长度
n = listlen(str2); //求str2的长度
for(p = str1;m > n;m --){ //若m>n,则p指向链表中第m-n+1个结点
p = p -> next; //使p指向的链表与q指向的链表等长
}
for(q = str2;m < n;n --){ //若m<n,则q指向链表中第n-m+1个结点
q = q -> next; //使q指向的链表与p指向的链表等长
}
while(p -> next != NULL && p -> next != q -> next){ //将指针p和q同步向后移动
p = p -> next;
q = q -> next;
}
return p -> next; //返回共同后缀的起始地址
}