本文共 3696 字,大约阅读时间需要 12 分钟。
双头链表(OrIGHL Link List)是一种节省存储空间的数据结构,当两个字符串结尾有相同的部分,双头链表允许这些相同的结点共享存储空间。以下是实现双头链表和查找公共后缀起始位置的算法详细说明。
算法目标:根据两个字符串分别构建双头链表,在两个字符串末尾有相同字符的部分,允许它们共享结点存储空间。
实现步骤:
list1
和 list2
,它们各自的头结点初始化为空。str1
和 str2
的对应字符。str1
剩余字符依次插入 list1
。str2
剩余字符依次插入 list2
。示例代码:
// 初始化链表节点struct LNode { char data; LNode* next;};// 创建链表头结点辅助函数void initLinkList(LNode*& list) { list = new LNode; list->next = nullptr;}// 构建双头链表,共享相同的后缀存储空间void buildDoubleLinkedList(char* str1, char* str2, int m, int n, LNode*& list1, LNode*& list2) { list1 = list2 = nullptr; // 初始化双链表头指针为空 // 从字符串末尾开始,向前构建链表 int i = m - 1, j = n - 1; LNode* current; while (i >= 0 && j >= 0 && str1[i] == str2[j]) { current = new LNode; current->data = str1[i]; current->next = list1; // 将当前结点连接到已有链表 list1 = current; --i, --j; current = nullptr; // 循环后,current指针重置为null } // 共享当前链表的结尾节点 list2 = list1; // 处理剩余部分,将其插入链表中 // 处理str1的剩余部分 while (i >= 0) { current = new LNode; current->data = str1[i]; current->next = list1; list1 = current; --i; } // 处理str2的剩余部分 while (j >= 0) { current = new LNode; current->data = str2[j]; current->next = list2; list2 = current; --j; } // 添加头结点 list1 = new LNode; list1->next = list1; list2 = new LNode; list2->next = list2;}
算法目标:找到两个双头链表的共同后缀起始节点位置,返回该节点的指针。
实现步骤:
示例代码:
// 计算链表长度int getLength(LNode* head) { int len = 0; LNode* current = head->next; // 除去头结点 while (current) { len++; current = current->next; } return len;}// 查找双头链表的公共后缀起始位置LNode* findCommonSuffixStart(LNode* listA, LNode* listB) { int lenA = getLength(listA); int lenB = getLength(listB); LNode* longList; // 长度较长的链表指针 LNode* shortList; // 较短的链表指针 int len = (lenA > lenB) ? (lenA - lenB) : (lenB - lenA); // 调整指针使两个链表尾部对齐 if (lenA > lenB) { longList = listA->next; // Skip 'lenB' 个节点后到达较长链表尾部 shortList = listB->next; // 长度不变 len = lenB; } else { longList = listB->next; shortList = listA->next; len = lenA; } // 同时移动两个链表的尾部指针 while (len-- >= 0 && longList && shortList) { longList = longList->next; if (longList && shortList && longList == shortList) { return longList; // 返回首个公共节点 } shortList = shortList->next; } return nullptr; // 无公共后缀时返回空}
// 测试构建链表和查找公共后缀int main() { string str1 = "abcdxyz", str2 = "abcdefghijk"; // 初始化链表存储空间 LNode* list1 = new LNode, *list2 = new LNode; // 头结点(双头链表) // 构建双头链表 int m = str1.size(), n = str2.size(); char* s1 = new char[m], s2 = new char[n]; memcpy(s1, str1.c_str(), m); memcpy(s2, str2.c_str(), n); buildDoubleLinkedList(s1, s2, m, n, list1, list2); // 打印双头链表内容 cout << "list1: "; printList(list1); cout << "list2: "; printList(list2); // 查找公共后缀开始的结点 LNode* commonNode = findCommonSuffixStart(list1->next, list2->next); if (commonNode) { cout << "第一个公共后缀的起始节点: " << commonNode->data << endl; } else { cout << "没有公共后缀" << endl; } return 0;}
注意事项:
转载地址:http://rehkk.baihongyu.com/