23.[2012 统考真题]假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时可共享相同的后缀存储空间,例如,“loading”和“being”的存储映像设 strl和str2分别指向两个单词所在单链表的头结点,链表结点结构为datanext请设计一个时间上尽可能高效的算法,找出由 str1和 str2 所指向两个链表共同后缀的起始位置
目录
本题代码如下
可以这样计算链表长度
完整测试代码
本题代码如下
//我这个在外面已经计算好了两个字符串的长度,所以直接传值进去了
linklist find(linklist *L1,linklist *L2,int sza,int szb)
{
lnode* p, * q;
for (p = *L1; sza > szb; sza--)//若sza>szb,使p指向链表中的第m-n+1个结点
p = p->next;
for (q = *L2; szb > sza; szb--)//若szb>sza,使q指向链表中的第n-m+1个结点
q = q->next;
while (p->next!=NULL&&p->next->data!=q->next->data)//将p与q同步后移
{
p = p->next;
q = q->next;
}
return p->next;//返回公共后缀的起始地址
}
int listlen(linklist *L)
{
int len=0;
while((*L)->next!=NULL)
{
len++;
*L=(*L)->next;
}
return len;
}
#include
#include
typedef struct lnode
{
char data;
struct lnode* next;
}lnode, * linklist;
char a[7] = { "loading" };
char b[5] = { "being" };
int len(char arr[])
{
int i = 0;
int count = 0;
for (i = 0; arr[i] != '\0'; i++)
count++;
return count;
}
void buildlinklist(linklist* L,char arr[],int n)
{
*L = (lnode*)malloc(sizeof(lnode));
(*L)->next = NULL;
lnode* s = *L, * r = *L;
int i = 0;
for (i = 0; i < n; i++)
{
s = (lnode*)malloc(sizeof(lnode));
s->data = arr[i];
s->next = r->next;
r->next = s;
r = s;
}
r->next = NULL;
}
linklist find(linklist *L1,linklist *L2,int sza,int szb)//我这个在外面已经计算好了两个字符串的长度,所以直接传值进去了
{
lnode* p, * q;
for (p = *L1; sza > szb; sza--)
p = p->next;
for (q = *L2; szb > sza; szb--)
q = q->next;
while (p->next!=NULL&&p->next->data!=q->next->data)
{
p = p->next;
q = q->next;
}
return p->next;
}
void print(linklist *L)
{
lnode* k = (*L)->next;
while (k)
{
printf("%c ", k->data);
k = k->next;
}
}
int main()
{
int sza = len(a);
int szb = len(b);
linklist L1,L2;
buildlinklist(&L1,a,sza);
printf("原始的L1单链表为:");
print(&L1);
buildlinklist(&L2, b, szb);
printf("\n原始的L2单链表为:");
print(&L2);
linklist C=find(&L1, &L2, sza, szb);
printf("\n公共首结点为:%c", C->data);
return 0;
}
也可以这样写(差不多的思路)其实也还可以暴力求解(这里就没写啦)
linklist find(linklist* L1, linklist* L2, int sza, int szb)
{
lnode* p=(*L1)->next, * q=(*L2)->next;
if (sza > szb)//如果sza大于szb
{
int dist = sza - szb;
for (int i = 0; i < dist; i++)//让p移动到与q到表尾长度相同的位置
p = p->next;
}
if (sza < szb)//如果sza小于szb
{
int dist = szb - sza;
for (int i = 0; i < dist; i++)//让q移动到与p到表尾长度相同的位置
q = q->next;
}
while (p && q)//一起向后遍历
{
if (p->data == q->data)//遇到了就返回结点的值
return p;
else
{
p = p->next;
q = q->next;
}
}
return 0;
}
完整测试代码为
#include
#include
typedef struct lnode
{
char data;
struct lnode* next;
}lnode, * linklist;
char a[7] = { "loading" };
char b[5] = { "being" };
int len(char arr[])
{
int i = 0;
int count = 0;
for (i = 0; arr[i] != '\0'; i++)
count++;
return count;
}
void buildlinklist(linklist* L, char arr[], int n)
{
*L = (lnode*)malloc(sizeof(lnode));
(*L)->next = NULL;
lnode* s = *L, * r = *L;
int i = 0;
for (i = 0; i < n; i++)
{
s = (lnode*)malloc(sizeof(lnode));
s->data = arr[i];
s->next = r->next;
r->next = s;
r = s;
}
r->next = NULL;
}
linklist find(linklist* L1, linklist* L2, int sza, int szb)//我这个在外面已经计算好了两个字符串的长度,所以直接传值进去了
{
lnode* p=(*L1)->next, * q=(*L2)->next;
if (sza > szb)//如果sza大于szb
{
int dist = sza - szb;
for (int i = 0; i < dist; i++)//让p移动到与q到表尾长度相同的位置
p = p->next;
}
if (sza < szb)//如果sza小于szb
{
int dist = szb - sza;
for (int i = 0; i < dist; i++)//让q移动到与p到表尾长度相同的位置
q = q->next;
}
while (p && q)//一起向后遍历
{
if (p->data == q->data)//遇到了就返回结点的值
return p;
else
{
p = p->next;
q = q->next;
}
}
return 0;
}
void print(linklist* L)
{
lnode* k = (*L)->next;
while (k)
{
printf("%c ", k->data);
k = k->next;
}
}
int main()
{
int sza = len(a);
int szb = len(b);
linklist L1, L2;
buildlinklist(&L1, a, sza);
printf("原始的L1单链表为:");
print(&L1);
buildlinklist(&L2, b, szb);
printf("\n原始的L2单链表为:");
print(&L2);
linklist C = find(&L1, &L2, sza, szb);
printf("\n公共首结点为:%c", C->data);
return 0;
}