数据结构–就地逆置匹配子串的C语言实现(超详细注释/实验报告)
实验题目
在计算机科学中,就地逆置匹配子串问题是将所给的主串中的所给的一个子串(给定的)逆置(如果不是子串的话就不逆置)。
实验目的
通过解决就地逆置匹配子串的问题,提升对串的理解。
实验要求
用户输入一个主串和一个子串,实现就地逆置匹配子串的操作。
实验内容和实验步骤
1.需求分析
用户输入一个主串和一个子串,就地逆置匹配子串
2. 概要设计
设计几个函数实现以下操作
- 就地逆置s中的t子串
- 输入一个串,输入“#”来停止输入
- 打印串
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);
}