P38.22
有A、B两个字符串,以链表形式存放。他们有相同的后缀,请给出后缀的第一个字母。
(1)算法的基本设计思想
分别遍历一遍链表并将其倒置为新的链表。则两个新的链表的第一个不同的元素之前的元素就是所需的元素。
倒置采用的是头插法来生成两个新的链表。
(2)代码如下
#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode, *LinkList;
void printList(LinkList &L)
{
printf("\n");
LNode *s=L->next;
while (s != NULL)
{
printf("%c", s->data);
s = s->next;
}
}
LinkList CreatListend(LinkList &L,LinkList &end)
{
char x;
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
scanf("%c", &x);
while (x != '@')
{
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;
scanf("%c", &x);
}
end = r;
r->next = NULL;
return L;
}
void main()
{
int count;
LinkList L1, L2, L3;
LinkList _L1, _L2;
LinkList end1=NULL, end2=NULL,end3=NULL;
CreatListend(L1,end1);
CreatListend(L2,end2);
CreatListend(L3,end3);
end1->next = L3->next->next;
end2->next = L3->next->next;
printList(L1);
printList(L2);
_L1= (LinkList)malloc(sizeof(LNode));
_L2= (LinkList)malloc(sizeof(LNode));
_L1->next = NULL;
_L2->next = NULL;
LNode *s1,*s2;
while (L1 != NULL)
{
s1 = (LNode*)malloc(sizeof(LNode));
s1->data = L1->data;
s1->next = _L1->next;
_L1->next = s1;
L1 = L1->next;
}
while (L2 != NULL)
{
s2 = (LNode*)malloc(sizeof(LNode));
s2->data = L2->data;
s2->next = _L2->next;
_L2->next = s2;
L2 = L2->next;
}
if (_L1->data != _L2->data)
printf("无共同后缀");
else
while (_L1->next->data == _L2->next->data)
{
_L1 = _L1->next;
_L2 = _L2->next;
}
printf("后缀起始字母为%c", _L1->data);
}
(3)复杂度
时间复杂度O(n)
空间复杂度O(n)
较好的算法
(1)算法的基本设计思想
曾经考虑过这样一个算法,但是由于对指针指向不是很熟练而放弃。就是设置两个指针,分别指向两链表。向后移动,直到两指针的地址相同时就是后缀的第一个字母。当然该算法需要知道两个链表各自的长度,因此时间上也没有好多少。
(2)代码
#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode, *LinkList;//LNode是结构变量,LinkList是结构指针
int countList(LinkList &L)
{
int count = 0;
LNode *s = L->next;
while (s != NULL)
{
s = s->next;
count++;
}
return count;
}
void printList(LinkList &L)
{
printf("\n");
LNode *s=L->next;
while (s != NULL)
{
printf("%c", s->data);
s = s->next;
}
}
LinkList CreatListend(LinkList &L,LNode* &end)//返回的尾指针的类型应该是结构指针LinkList,也可以是LNode*,不能是结构变量LNode。当然要改变它的值,那么传入的就得是地址了
{
char x;
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
scanf("%c", &x);
while (x != '\n')
{
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;
scanf("%c", &x);
}
end = r;
r->next = NULL;
return L;
}
void main()
{
int count;
LinkList L1, L2, L3;
LinkList end1=NULL, end2=NULL,end3=NULL;
CreatListend(L1,end1);
CreatListend(L2,end2);
CreatListend(L3,end3);
end1->next = L3->next;
end2->next = L3->next;
printList(L1);
printList(L2);
int count1 = countList(L1);
int count2 = countList(L2);
LNode *p, *q;
for (p = L1; count1 > count2; count1--)
p = p->next;
for (q = L2; count1 < count2; count2--)
q = q->next;
while (p->next != NULL&&p->next != q->next)
{
p = p->next;
q = q->next;
}
if (p->next == NULL)
printf("无共同后缀");
else
printf("后缀起始字母为%c", p->next->data);
}
(3)复杂度
时间复杂度O(n)
空间复杂度O(n)
PS:
人家的算法肯定符合要求,人家返回的是地址,我返回的是值。而且当我的在后缀之前有一个字母是相同的时候,就出现了错误。总而言之还是我蠢。