博客
关于我
建立双头链表及判断两个链表共同后缀的起始位置
阅读量:785 次
发布时间:2019-03-24

本文共 3696 字,大约阅读时间需要 12 分钟。

双头链表(OrIGHL Link List)是一种节省存储空间的数据结构,当两个字符串结尾有相同的部分,双头链表允许这些相同的结点共享存储空间。以下是实现双头链表和查找公共后缀起始位置的算法详细说明。

1. 建立双头链表

算法目标:根据两个字符串分别构建双头链表,在两个字符串末尾有相同字符的部分,允许它们共享结点存储空间。

实现步骤

  • 初始化两个链表头结点:创建两个链表对象 list1list2,它们各自的头结点初始化为空。
  • 构建二者共同的后缀部分
    • 从字符串末尾开始向前遍历,比较 str1str2 的对应字符。
    • 当发现字符相同时,创建新节点将其插入链表,共享存储空间。
    • 停止异常字符比较时(字符不同)。
  • 处理剩余部分
    • 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;}

    2. 查找双头链表的公共后缀起始位置

    算法目标:找到两个双头链表的共同后缀起始节点位置,返回该节点的指针。

    实现步骤

  • 计算链表长度:获取两个链表的长度。
  • 确定遍历顺序:较长链表先进行长度差量的移动,确保两个指针同时到达最后一个节点。
  • 同步遍历:同时遍历长链表和短链表,并比较对应节点,直到找到相同的节点。
  • 返回起始节点:找到第一个公共节点即为共同后缀的起始点。
  • 示例代码

    // 计算链表长度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;  // 无公共后缀时返回空}

    3. 测试示例

    // 测试构建链表和查找公共后缀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;}

    4. 功能说明

    • buildDoubleLinkedList:根据给定字符串构建双带链表,在尾部存在相同字符的条目会共享存储。
    • findCommonSuffixStart:返回两个双档链表的第一个共同节点,即后缀的开始位置。
    • getLength:计算链表的长度。
    • printList:输出链表内容,并用空格分隔每个节点的数据。

    注意事项

    • 确保在动态内存分配时避免指针泄漏。
    • 为每个链表分配足够的内存空间。
    • 适用于字符串互相后缀可能为空的情况。

    转载地址:http://rehkk.baihongyu.com/

    你可能感兴趣的文章
    mysql-group_concat
    查看>>
    MySQL-redo日志
    查看>>
    MySQL-【1】配置
    查看>>
    MySQL-【4】基本操作
    查看>>
    Mysql-丢失更新
    查看>>
    Mysql-事务阻塞
    查看>>
    Mysql-存储引擎
    查看>>
    mysql-开启慢查询&所有操作记录日志
    查看>>
    MySQL-数据目录
    查看>>
    MySQL-数据页的结构
    查看>>
    MySQL-架构篇
    查看>>
    MySQL-索引的分类(聚簇索引、二级索引、联合索引)
    查看>>
    Mysql-触发器及创建触发器失败原因
    查看>>
    MySQL-连接
    查看>>
    mysql-递归查询(二)
    查看>>
    MySQL5.1安装
    查看>>
    mysql5.5和5.6版本间的坑
    查看>>
    mysql5.5最简安装教程
    查看>>
    mysql5.6 TIME,DATETIME,TIMESTAMP
    查看>>
    mysql5.6.21重置数据库的root密码
    查看>>