假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,可共享相同的后缀存储空间,例如,“loading”,“being”的存储映像如下图所示。
设str1和str2分别指向两个单词所在单链表的头结点,链表结点结构为
data next
请设计一个时间上尽可能高效的算法,找出由str1和str2所指向两个链表共同后缀的起始位置(如图中字符i所在结点的位置p)
算法思想:
1.遍历两个单链表,分别计算出它们的长度。
2.如果两个链表的长度不相同,则将较长的那个链表的头指针往后移,使得两个链表剩余的长度相同。
3.同时遍历两个链表,比较节点是否相同,直至找到第一个相同的节点或遍历到链表的结尾。
4.输出或返回第一个相同节点的位置。
代码:(完整理解此题)
#include <stdio.h>
#include <stdlib.h>struct ListNode {char data;struct ListNode* next;
};struct ListNode* findCommonSuffix(struct ListNode* str1, struct ListNode* str2) {int len1 = getListLength(str1);int len2 = getListLength(str2);// 将较长链表的头指针向后移动,使得两个链表剩余的长度相等if (len1 > len2) {str1 = moveHead(str1, len1 - len2);} else if (len2 > len1) {str2 = moveHead(str2, len2 - len1);}// 同时遍历两个链表,比较节点是否相同while (str1 != NULL && str2 != NULL) {if (str1 == str2) {return str1; // 找到第一个相同的节点}str1 = str1->next;str2 = str2->next;}return NULL; // 没有找到共同后缀
}// 获取链表的长度
int getListLength(struct ListNode* head) {int length = 0;while (head != NULL) {length++;head = head->next;}return length;
}// 将链表的头指针向后移动指定步数
struct ListNode* moveHead(struct ListNode* head, int steps) {for (int i = 0; i < steps; i++) {head = head->next;}return head;
}int main() {// 构建示例链表struct ListNode* node1 = (struct ListNode*)malloc(sizeof(struct ListNode));node1->data = 'l';node1->next = NULL;struct ListNode* node2 = (struct ListNode*)malloc(sizeof(struct ListNode));node2->data = 'o';node2->next = NULL;struct ListNode* node3 = (struct ListNode*)malloc(sizeof(struct ListNode));node3->data = 'a';node3->next = NULL;struct ListNode* node4 = (struct ListNode*)malloc(sizeof(struct ListNode));node4->data = 'd';node4->next = NULL;struct ListNode* node5 = (struct ListNode*)malloc(sizeof(struct ListNode));node5->data = 'i';node5->next = NULL;struct ListNode* node6 = (struct ListNode*)malloc(sizeof(struct ListNode));node6->data = 'n';node6->next = NULL;struct ListNode* node7 = (struct ListNode*)malloc(sizeof(struct ListNode));node7->data = 'g';node7->next = NULL;// 构建链表结构node1->next = node2;node2->next = node3;node3->next = node4;node4->next = node5;node5->next = node6;node6->next = node7;struct ListNode* str1 = node1;// 构建示例链表struct ListNode* node8 = (struct ListNode*)malloc(sizeof(struct ListNode));node8->data = 'b';node8->next = NULL;struct ListNode* node9 = (struct ListNode*)malloc(sizeof(struct ListNode));node9->data = 'e';node9->next = NULL;struct ListNode* node10 = (struct ListNode*)malloc(sizeof(struct ListNode));node10->data = 'i';node10->next = NULL;struct ListNode* node11 = (struct ListNode*)malloc(sizeof(struct ListNode));node11->data = 'n';node11->next = NULL;struct ListNode* node12 = (struct ListNode*)malloc(sizeof(struct ListNode));node12->data = 'g';node12->next = NULL;// 构建链表结构node8->next = node9;node9->next = node10;node10->next = node11;node11->next = node12;struct ListNode* str2 = node8;// 调用函数查找共同后缀struct ListNode* commonSuffix = findCommonSuffix(str1, str2);if (commonSuffix != NULL) {printf("共同后缀的起始位置为:%c\n", commonSuffix->data);} else {printf("未找到共同后缀\n");}// 释放内存free(node1);free(node2);free(node3);free(node4);free(node5);free(node6);free(node7);free(node8);free(node9);free(node10);free(node11);free(node12);return 0;
}{
}