数据结构--就地逆置匹配子串的C语言实现(超详细注释/实验报告)

数据结构–就地逆置匹配子串的C语言实现(超详细注释/实验报告)

实验题目

在计算机科学中,就地逆置匹配子串问题是将所给的主串中的所给的一个子串(给定的)逆置(如果不是子串的话就不逆置)。

实验目的

通过解决就地逆置匹配子串的问题,提升对串的理解。

实验要求

用户输入一个主串和一个子串,实现就地逆置匹配子串的操作。

实验内容和实验步骤

1.需求分析

用户输入一个主串和一个子串,就地逆置匹配子串

2. 概要设计

设计几个函数实现以下操作

  1. 就地逆置s中的t子串
  2. 输入一个串,输入“#”来停止输入
  3. 打印串

3. 详细设计

导入一些库并定义最大串长和串的基本类型(链串)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef char elementype;
typedef struct node
{
    elementype data;
    struct node *next;
} linkstr;

就地逆置s中的t子串

linkstr *invertsubstring(linkstr *s, linkstr *t)
{//就地逆置s中的t子串
    linkstr *begin, *p, *t1, *r, *q, *u, *pr;

    pr = s;
    p = s;
    t1 = t;


    while (p != NULL && t1 != NULL)
    {//这一部分是寻找到子串在主串的位置
        if (p->data == t1->data)
        {
            p = p->next;
            t1 = t1->next;
        }
        else
        {
            begin = pr;
            pr = pr->next;
            p = pr;
            t1 = t;
        }
    }
//    printf("就地逆置开始\n");
    if (t1 != NULL)
    {
        printf("主串中没有匹配的子串\n");
        return s;
    }
    else
    {//这一部分是逆置操作
        q = begin->next;
        r = q->next;
        q->next = p;
        while (r != p)
        {
            u = r->next;
            r->next = q;
            q = r;
            r = u;
        }
        begin->next = q;
    }
    return s;

}

输入一个串,输入“#”来停止输入

linkstr *crtlinked()
{//输入一个串,输入“#”来停止输入
    linkstr *s, *p, *head;
    char ch;

    head = NULL;
    p = head;
    //getchar();
//    printf("\n请输入你的串(输入‘#’,停止输入):\n");
//    printf("(输入‘#’,停止输入):\n");
//    printf("如果你想停止输入,就请输入'#' :\n");
    scanf("%c", &ch);
    while (ch != '#')
    {
        s = (linkstr *) malloc(sizeof(linkstr));
        s->data = ch;
        if (head == NULL)
            head = s;
        else p->next = s;
        p = s;
        scanf("%c", &ch);
    }
    p->next = NULL;

    return head;
}

打印串的操作

void print_link(linkstr *s)
{//打印串的操作
    linkstr *v;
    v = s;

    while (v)
    {
//        printf("%c  -> ", v->data);
        if(v->next)
            printf("%c -> ", v->data);
        else
            printf("%c  ", v->data);
        v = v->next;
    }
    printf("\n");
}

主函数部分

  • 实现的操作就是用户输入两个串,然后调用函数输出结果。
void main()
{
    linkstr *s, *t, *m;
    s = (linkstr *) malloc(sizeof(linkstr));
    t = (linkstr *) malloc(sizeof(linkstr));

    printf("请输入主串(输入‘#’,停止输入):\n");
    s = crtlinked();
    printf("主串:\n");
    print_link(s);
    getchar();

    printf("请输入需要就地逆置的子串(输入‘#’,停止输入):\n");
    t = crtlinked();
    printf("子串:\n");
    print_link(t);
    m = (linkstr *) malloc(sizeof(linkstr));
    m = invertsubstring(s, t);
    printf("就地逆置后的串:\n");
    print_link(m);
}

4. 调试分析

遇到的问题及解决方法
  • 算法原理有一丝复杂,多看看然后举例子就理解了
算法的时空分析

这个算法最多只有一层循环,并且采用了动态存储,时空复杂度都很不错。

实验结果

在这里插入图片描述
实验结果很不错!

实验总结

相比于原代码,改进了显示上的一些操作,使得界面更加美观。
就地逆置匹配子串的原理很有意思,要反复好好体会,多多重复,百炼成钢!

最后附上完整的代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef char elementype;
typedef struct node
{
    elementype data;
    struct node *next;
} linkstr;


linkstr *invertsubstring(linkstr *s, linkstr *t)
{//就地逆置s中的t子串
    linkstr *begin, *p, *t1, *r, *q, *u, *pr;

    pr = s;
    p = s;
    t1 = t;


    while (p != NULL && t1 != NULL)
    {//这一部分是寻找到子串在主串的位置
        if (p->data == t1->data)
        {
            p = p->next;
            t1 = t1->next;
        }
        else
        {
            begin = pr;
            pr = pr->next;
            p = pr;
            t1 = t;
        }
    }
//    printf("就地逆置开始\n");
    if (t1 != NULL)
    {
        printf("主串中没有匹配的子串\n");
        return s;
    }
    else
    {//这一部分是逆置操作
        q = begin->next;
        r = q->next;
        q->next = p;
        while (r != p)
        {
            u = r->next;
            r->next = q;
            q = r;
            r = u;
        }
        begin->next = q;
    }
    return s;

}

linkstr *crtlinked()
{//输入一个串,输入“#”来停止输入
    linkstr *s, *p, *head;
    char ch;

    head = NULL;
    p = head;
    //getchar();
//    printf("\n请输入你的串(输入‘#’,停止输入):\n");
//    printf("(输入‘#’,停止输入):\n");
//    printf("如果你想停止输入,就请输入'#' :\n");
    scanf("%c", &ch);
    while (ch != '#')
    {
        s = (linkstr *) malloc(sizeof(linkstr));
        s->data = ch;
        if (head == NULL)
            head = s;
        else p->next = s;
        p = s;
        scanf("%c", &ch);
    }
    p->next = NULL;

    return head;
}

void print_link(linkstr *s)
{//打印串的操作
    linkstr *v;
    v = s;

    while (v)
    {
//        printf("%c  -> ", v->data);
        if(v->next)
            printf("%c -> ", v->data);
        else
            printf("%c  ", v->data);
        v = v->next;
    }
    printf("\n");
}

void main()
{
    linkstr *s, *t, *m;
    s = (linkstr *) malloc(sizeof(linkstr));
    t = (linkstr *) malloc(sizeof(linkstr));

    printf("请输入主串(输入‘#’,停止输入):\n");
    s = crtlinked();
    printf("主串:\n");
    print_link(s);
    getchar();

    printf("请输入需要就地逆置的子串(输入‘#’,停止输入):\n");
    t = crtlinked();
    printf("子串:\n");
    print_link(t);
    m = (linkstr *) malloc(sizeof(linkstr));
    m = invertsubstring(s, t);
    printf("就地逆置后的串:\n");
    print_link(m);
}
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值