数据结构代码集训day11(适合考研、自学、期末和专升本)

今日习题来自B站up:白话拆解数据结构


题目如下:

1、判断B链表的值是否是A链表值的连续子序列

2、假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,则可共享相同的后缀存储空间,例如,"loading"和"being"的存储映像如下图所示。

设str1和str2分别指向两个单词所在单链表的头结点,链表结点结构为{datanext},请设计一个时间上尽可能高效的算法,找出由str1和str2所指向两个链表共同后缀的起始位置(如图中字符i所在结点的位置p)。要求:

(1)给出算法的基本设计思想。
(2)根据设计思想,采用C或 C++语言描述算法,关键之处给出注释。
(3)说明你所设计算法的时间复杂度。


题1

这个好说,因为加了一堆限制条件,连续子序列就是得一个个比,比不成功就从头开始比,就完全类似于模式串的暴力匹配。

bool xulie(Linklist A,Linklist B){

Lnode *p,*q,*s;

p=A->next; //p、q用来遍历

q=B->next;

s=A->next; // s用来指示a表的下一次匹配开始位置

while(p&&q){

if(s->data==q->data){ //第一个值匹配成功了,就接着匹配

s=s->next;

q=q->next;

}

else{ // 匹配不成功,就重新来

p=p->next;

s=p;

q=B->next;

}

}

if(!q) return true; // 匹配成功一定是q指向空了

if(q) return false;

}

演示一下:

完整代码如下:

cpp 复制代码
#include <iostream>
#include <cstdio>
#include <ctime>

using namespace std;

// 单链表结构体定义
typedef struct Lnode{
    int data;
    Lnode *next;
}Lnode,*Linklist;

Linklist list_insertbytail(Linklist &L){
    Lnode *s;
    int x;
    L = (Lnode*)malloc(sizeof(Lnode));
    L->next = NULL;
    Lnode *r = L;
    cin >> x;
    while(x!=9999){
        s = (Lnode*)malloc(sizeof(Lnode));
        s->data=x;
        s->next=NULL;

        r->next = s;
        r=r->next;
        cin >> x;
    }
    return L;
}

// 判断B链表是否是A链表的连续子序列
bool xulie(Linklist A,Linklist B){
    Lnode *p,*q,*s;
    p=A->next;
    q=B->next;
    s=A->next;
    while(p&&q){
       if(s->data==q->data){
        s=s->next;
        q=q->next;
       }
       else{
        p=p->next;
        s=p;
        q=B->next;
       }
    }
    if(!q)  return true;
    if(q)   return false;
}

int main(){
    Linklist A,B;
    list_insertbytail(A);
    list_insertbytail(B);

    printf("\n");
    if(xulie(A,B))
        printf("success find\n");
    else printf("None");
    return 0;
}

题2

结合题目图片来看,我们要做的事情如下:

(1)确定两个表的表长

(2)遍历两个表,找到第一个地址相等的位置

现在来说为什么要做(1),我们假设两个表表长不相等,而我们找到p结点位置只能通过指针向后遍历,如果从表头开始找,因为表长不相等,一定会错过;如果嵌套循环来找,复杂度又太高了。

所以我们可以先计算表长,让两个指针对齐开始往后找,可以省略很多不必要的麻烦。

通过(1),我们对齐了指针,就可以让指针同步往后找,因为本题让我们找的是位置,所以我们拿一个指针指向它,返回这个指针就行了,因为指针存的不就是地址嘛

int listlength(Linklist L){

Lnode *p=L->next;

int i=1;

for(;p;i++,p=p->next);

return i;

}

//找两个链表公共后缀的起始位置

Linklist loc(Linklist str1,Linklist str2){

Lnode *p,*q;

p=str1->next;

q=str2->next;

int str1_length=listlength(str1); // 求表长

int str2_length=listlength(str2);

int s = str1_length-str2_length;

// 指针对齐

if(s > 0){

for(int i=0;i<s;i++,p=p->next);

}

else{

for(int i=0;i<-s;i++,q=q->next);

}

while(p&&q){

if(p==q) return p; // 返回p还是q都可以

else{

p=p->next;

q=q->next;

}

}

return nullptr; //没找到

}

演示一下:

完整代码如下:

cpp 复制代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <ctime>

using namespace std;

// 结构体定义
typedef struct Lnode{
    char data;
    Lnode *next;
}Lnode,*Linklist;

Linklist list_insertbytail(Linklist &L){
    Lnode *s;
    char x;
    L = (Lnode*)malloc(sizeof(Lnode));
    L->next = NULL;
    Lnode *r = L;
    cin >> x;
    while(x!='z'){
        s = (Lnode*)malloc(sizeof(Lnode));
        s->data=x;
        s->next=NULL;

        r->next = s;
        r=r->next;
        cin >> x;
    }
    return L;
}
int listlength(Linklist L){
    Lnode *p=L->next;
    int i=1;
    for(;p;i++,p=p->next);
    return i;
}
//找两个链表公共后缀的起始位置
Linklist loc(Linklist str1,Linklist str2){
    Lnode *p,*q;
    p=str1->next;
    q=str2->next;
    int str1_length=listlength(str1);
    int str2_length=listlength(str2);
    int s = str1_length-str2_length;
    if(s > 0){
        for(int i=0;i<s;i++,p=p->next);
    }
    else{
        for(int i=0;i<-s;i++,q=q->next);
    }

    while(p&&q){
        if(p==q)    return p;
        else{
            p=p->next;
            q=q->next;
        }
    }
    return nullptr;
}

int main(){
    Linklist A, B;

    cout << "请输入链表A的元素(以'z'结束):" << endl;
    list_insertbytail(A);
    cout << "请输入链表B的元素(以'z'结束):" << endl;
    list_insertbytail(B);

    Lnode *p = loc(A, B);
    if (p) {
        cout << "公共序列为:" << endl;
        for (; p; p = p->next)
            printf("%c -> ", p->data);  
        printf("NULL\n");
    } else {
        cout << "没有公共后缀。" << endl;
    }
    return 0;
}
相关推荐
唐维康25 分钟前
2027昆明理工大学机械考研分析:机械工程专硕157人占六成
考研·昆明理工大学
Logic1011 小时前
C语言/数据结构位运算题解:异或XOR找出多任务下载器中的“独特下载速度“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
Discipline10292 小时前
尼泊尔河流流量:天气驱动的预测与高流量风险
人工智能·算法
XuCoder2 小时前
改一个数,右边全得重算,这题怎么扛住两万次查询
算法
小羊没烦恼!2 小时前
在Scrum中实施敏捷建模
java·开发语言·windows·算法·c#
weixin_307779132 小时前
基于睿擎工业开发平台的预训练视觉模型轻量化适配与低代码部署优化
开发语言·算法
hold?fish:palm3 小时前
45 二叉树的右视图
开发语言·c++·算法
粤鼎恒业3 小时前
惠州工厂电子料回收厂家推荐:从交接单反推筛选标准
大数据·数据库·算法·硬件架构·硬件工程·pcb工艺·材料工程
小爷毛毛(卓寿杰)4 小时前
【Agent 意图识别】输出协议、评估与置信度
人工智能·算法·大模型·prompt·大语言模型·agent
优质酸酸乳4 小时前
力扣100题之21合并两个有序链表
算法·leetcode·链表