#include
using namespace std;
/*
下面我们写一下链串的数据结构和 *** 作定义
串采用链式存储结构存储时称为链串,这里采用带头结点的单链表作为链串。
链串的组织形式与一般的单链表类似,主要区别在于链串中的一个结点可以存储多个字符,通常将链串中的每个结点所存储的字符个数称为结点大小
当结点大小大于1时,链串的尾结点的各个数据域不一定总能全被字符占满,此时应在这些未占用的数据域里补上不属于字符集的特殊字符,以示区别
*/
//此处规定链串结点大小均为1
typedef struct snode
{
char data;//存放一个字符
struct snode* next;//指向下一个结点的指针
}LinkStrNode;//链串的结点类型
void StrAssign(LinkStrNode*& s, char cstr[])//使用尾插法建立链串,同时一个字符串常量是以‘//尾插法顺序与数组一致’标识结尾赋给链串s,即生成一个其值等于cstr的链串s
{ int
; i*
LinkStrNode, r* ; p//尾插法都是要使用两个指针的=
s new ; LinkStrNode//分配存储空间=
r ; s//r指向sfor
( =i 0 ;[ cstr]i!= ';' ++) i=new
{
p ; = LinkStrNode[
p->data ] cstr;i=;
r->next = p;
r } p=
NULL
r->next ; //尾结点的next域置为空}void
DestroyStr
( *&LinkStrNode)//销毁串,过程与销毁带头结点的单链表运算的实现过程相同 s*=
{
LinkStrNode, pre * s= ; p //都是需要使用两个指针来进行销毁串的 *** 作 s->nextwhile(
!= NULLp ) //扫描链串,直到尾结点的nextdelete;
{
= pre;
pre //两个结点同步后移一个结点 p= ;
p } pre->nextdelete
;
//释放最后一个结点,p指向NULL pre}void
StrCopy
( *&LinkStrNode,* s) LinkStrNode//将链串t复制给链串s,采用尾插法进行复制,过程和串的建立类似 t*=
{
LinkStrNode, p * t->next, * q; //由于还要一个指针指向t,所以需要三个指针 r=new
s ; //分配存储空间 LinkStrNode=;
r //r指向s swhile(
!= NULLp ) //扫描链串t=new
{
q ; = LinkStrNode;
q->data = p->data;
r->next = q;
r = q;
p } p->next=
NULL
r->next ; //尾结点的next域置为空}bool
StrEqual
( *,LinkStrNode* s) LinkStrNode//判断两个链串是否相等 t*=
{
LinkStrNode, p * s->next= ; q //使用两个指针分别指向两个链串 t->nextwhile(
!= NULLp && != NULL q && == ) p->data = q->data;
{
p = p->next;
q //两个链串长度相等,且对应位置的值相等 q->next}if
(
== NULLp && == NULL q ) //当两个都指向空时,两个链串相等returntrue
; elsereturn
false
; }int
StrLength
( *)LinkStrNode//求串长 sint=
{
0 i ; //用i来计算结点的个数,不包括其头结点*=
LinkStrNode; p while s->next(
!= NULLp ) ++;
{
i=;
p } p->nextreturn
;
} i*
Concat
LinkStrNode( *,LinkStrNode* s) LinkStrNode//两个串的连接,形成结果串,使用尾插法建立连接后的结果串str并且返回它 t*,
{
LinkStrNode* str= , p * s->next, * q; //str是需要返回的串,所以这里有四个指针 r=new
str ; = LinkStrNode;
r //指向结果串的尾结点 strwhile(
!= NULLp ) =new
{
q ; = LinkStrNode;
q->data = p->data;
r->next = q;
r = q;
p } p->next=
;
p while t->next(
!= NULLp ) =new
{
q ; = LinkStrNode;
q->data = p->data;
r->next = q;
r = q;
p } p->next//完全类似的过程
=NULL
r->next ; return;
} str*
SubStr
LinkStrNode( *,LinkStrNodeint s, int i) //返回链串中从第i个字符开始的由连续的j个字符组成的子串,当参数不正确时,返回一个空串 j//采用尾插法建立结果链串str并返回它int
{ ;
* k,
LinkStrNode* str= , p * s->next, * q; //尾插法一定要用两个指针,这里str是结果串,而p指向链串s r=new
str ; = LinkStrNodeNULL
str->next ; //置结果串为空串=;
r //r指向结果串的尾结点 strif(
<= 0i || StrLength ( i > )||s< 0 j||+ - i 1 j StrLength (>))sreturn;
//参数不正确时,返回空串 strfor(
= 1k ; <; k ++ i) k=;
p //一直循环,直到让p指向s的第i个数据结点 p->nextfor(
= 1k ; <=; k ++ j) k=new
{
q ; = LinkStrNode;
q->data = p->data;
r->next = q;
r = q;
p } p->next=
NULL
r->next ; return;
} str*
InsStr
LinkStrNode( *,LinkStrNodeint s, * i) LinkStrNode//将链串s2插入链串s1的第i个位置上,得到一个结果串,当参数不正确的时候返回一个结果串 tint;
{
* k,
LinkStrNode* str= , p * s->next= , p1 * t->next, * q; //这里为了方便起见,采用两个指针,分别指向链串s和链串t r=new
str ; = LinkStrNodeNULL
str->next ; =;
r //r指向结果串的尾结点 strif(
<= 0i || StrLength ( i > )+s1 ) //参数不正确时返回空串return;
for str(
= 1k ; <; k ++ i) k=new
{
q ; = LinkStrNode;
q->data = p->data;
r->next = q;
r = q;
p } p->nextwhile
(
!= NULLp1 ) =new
{
q ; = LinkStrNode;
q->data = p1->data;
r->next = q;
r = q;
p1 } p1->nextwhile
(
!= NULLp ) =new
{
q ; = LinkStrNode;
q->data = p->data;
r->next = q;
r = q;
p } p->next=
NULL
r->next ; return;
} str*
DelStr
LinkStrNode( *,LinkStrNodeint s, int i) //在链串s中删去从第i个字符开始的长度为j的子串,得到一个结果串。当参数不正确时,返回一个空串 jint;
{
* k,
LinkStrNode* str= , p * s->next, * q; = rnew
str ; = LinkStrNodeNULL
str->next ; if(
<= 0i || StrLength ( i > )||s< 0 j||+ - i 1 j StrLength (>))sreturn;
//返回空串 str=;
r //r指向结果串的尾结点 strfor(
= 1k ; <; k ++ i) k=new
{
q ; = LinkStrNode;
q->data = p->data;
r->next = q;
r = q;
p } p->nextfor
(
= 0k ; <; k ++ j) k=;
p //让p跳j个结点 p->nextwhile(
!= NULLp ) =new
{
q ; = LinkStrNode;
q->data = p->data;
r->next = q;
r = q;
p } p->next=
NULL
r->next ; return;
} str*
RepStr
LinkStrNode( *,LinkStrNodeint s, int i, * j) LinkStrNode//在链串s中将从第i字符开始的j个字符构成的子串用链串t替换,当参数不正确时,返回空串 tint;
{
* k,
LinkStrNode* str= , p * s->next= , p1 * t->next, * q; //这里为了方便起见,采用两个指针,分别指向链串s和链串t r=new
str ; = LinkStrNodeNULL
str->next ; =;
r //r指向结果串的尾结点 strif(
<= 0i || StrLength ( i > )||s< 0 j||+ - i 1 j StrLength (>))s//参数不正确时返回空串return;
for str(
= 1k ; <; k ++ i) k=new
{
q ; = LinkStrNode;
q->data = p->data;//这里没必要加上 q->next = NULL;
r->next = q;
r = q;
p } p->nextfor
(
= 0k ; <; k ++ j) k=;
p //让p跳j个结点 p->nextwhile(
!= NULLp1 ) =new
{
q ; = LinkStrNode;
q->data = p1->data;
r->next = q;
r = q;
p1 } p1->nextwhile
(
!= NULLp ) =new
{
q ; = LinkStrNode;
q->data = p->data;
r->next = q;
r = q;
p } p->next=
NULL
r->next ; return;
} strvoid
DispStr
( *)LinkStrNode//输出串s的所有元素值 s*=
{
LinkStrNode; p while s->next(
!= NULLp ) <<<<
{
cout " " p->data ; =;
p } p->next<<
;
cout } endl/*
出于节省时间的方面考虑,上面仅仅书写了链串的基本数据结构和其 *** 作,可以发现其很多 *** 作步骤都是
相同的、冗余的。
*/
/*
下面使用链串的数据结构来实现在串s中找到与串t相等的子串
这就是串的模式匹配
*/
//以上的链串不管怎么样都不能运行,我真的十分疑惑
int
/*int BF(LinkStrNode* s, LinkStrNode* t)
{
int i = 1, j = 1;
LinkStrNode* p = s->next, * q = t->next;//使用两个指针分别指向链串s和链串t
while (i < StrLength(s) && j < StrLength(t)&&p->data!=NULL&&q->data!=NULL)//两个串都没有扫描完时进行循环
{
if (p->data == q->data)//当前比较的两个字符相同
{
i++; j++;
p = p->next; q = q->next;
}
else
{
i = i - j + 1;
q = t->next; p = s->next;
for (int k = 1; k < i - j + 1; k++)
{
p = p->next;
}
//这样的过程和使用顺序串的过程完全是一致的
j = 1;
}
}
if (j >= StrLength(t))//j超界,表示t是s的子串
{
return (i - StrLength(t) + 1);//返回t在s中的位置,由链串表示就是第i-StrLength(t) + 1个结点开始的位置
}
else
return -1;//匹配失败则返回-1
}*/ main
( )/*char a[] = {'a','a','a','a','a','b','}'};
char b[] = { 'a','a','a','b','' };
LinkStrNode* s, * t;
StrAssign(s, a);
DispStr(s);
StrAssign(t, b);
DispStr(t);
int k = BF(s, t);
cout << k << endl;
DestroyStr(s);
DestroyStr(t);
*/
{
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)