c语言描述链串的类型定义,数据结构第四章:串

4.1 串类型的定义

字符串可以看作是一种特殊的线性表,字符串的数据对象约束为字符集(非数值数据)。

不同的应用所处理的串的特点亦不相同。

在线性表的基本操作中,大多以“单个元素”作为操作对象,而在串中则是以“串的整体”或一部分作为操作对象。

串的定义:

串(String)是零个或多个字符组成的有限序列。

一般记为:s=′a1a2…an′ (n≥0)

s是串的名字, a1a2…an是串s的值

ai可以是字母、数字或其它字符;

串内字符的数目n称为串的长度。

零个字符的串称为空串(null string),其长度为0。

子串:

串中任意个连续的字符组成的子序列称为该串的子串。

主串:

包含子串的串相应地称为主串。

字符的位置:

通常将字符在串中的序号称为该字符在串中的位置。

子串的位置:

以子串的第一个字符在主串中的位置来表示。

两个串相等:

当且仅当两个串的值相等时,称这两个串是相等的,即只有当两个串的长度相等, 并且每个对应位置的字符都相同时才相等。

关于串定义的说明:

串定义中的一对单引号本身不属于串!

其作用避免与变量名或数的常量混淆

空串(null string)和空格串(blank string)是不同的!

为了清晰起见,用符号“ø”表示“空串”

在操作上:

在线性表中,操作的对象基本上都是数据元素;

在串中,操作的对象通常以子串为单位。

例如:查找子串、求取子串、插入或删除子串等。

ad6fd4403c6710cfe3a4dcdaa02c1704.png

f73e8ab601ae7434743950121cd84a1d.png

f8265b0c8b1c260a426181bb030a7922.png

130a9db8cecea8d59b0ade29629d5413.png

对于串的基本操作集可以有不同的定义方法,在使用高级程序设计语言中的串类型时,应以该语言的参考手册为准。

在上述抽象数据类型定义的13种操作中,

串赋值 StrAssign、串复制 Strcopy、

串比较 StrCompare、求串长 StrLength、

串联接 Concat 以及求子串 SubString

等六种操作构成串类型的最小操作子集。

93d6233371d283d6bcdd71bd5b7883e7.png

fda568836dacacf21d0a6579642ba392.png

870e538f067391c5b368e8dfa21e979f.png

b0eb47f18cd0c22f44303b34377bc0b0.png

串的逻辑结构和线性表极为相似,区别仅在于串的数据对象约束为字符集。

串的基本操作和线性表有很大差别。

在线性表的基本操作中,大多以“单个元素”作为操作对象;

而在串的基本操作中,通常以“串的整体”作为操作对象。

在早期的程序设计语言中,串只是作为输入或输出的常量出现,则只需存储此串的串值,即字符序列即可。之后在多数非数值处理的程序中,串均以变量的形式出现,因此作为一个数据类型也就存在一个存储表示和实现的问题。

4.2 串的表示和实现

1.串的定长顺序存储表示

用一组地址连续的存储单元存储串值的字符序列。这是一种静态存储结构,串值的存储分配是在编译时完成的。因此,需要预先定义串的存储空间大小。

#define MAXSTRLEN 255; //定义能处理的最大的串长度

typedef unsigned char SString[MAXSTRLEN+1]; //0号单元存放串的长度

串的实际长度可在这个预定义长度的范围内随意设定,超过预定义长度的串值则被舍去,称之为“截断”。

串的联接算法

status ConCat(SString S1,SString S2,SString &T){

//用T返回由S1和S2联接而成的新串。若未截断,则返回TRUE,否则FALSE。

if(S1[0]+S2[0]<=MAXSTRLEN){ //未截断

T[1..S1[0]]=S1[1..S1[0]];

T[S1[0]+1..S1[0]+S2[0]]=S2[1..S2[0]];

T[0]=S1[0]+S2[0];

uncut=TRUE;

}

else if (S1[0]

T[1..S1[0]]=S1[1..S1[0]];

T[S1[0]+1..MAXSTRLEN]=S2[1..MAXSTRLEN-S1[0]];

T[0]=MAXSTRLEN;

uncat=FALSE;

}

else { //截断

T[0..MAXSTRLEN]=S1[0..MAXSTRLEN];

//T[0]= = S1[0]= = MAXSTRLEN

uncut = FALSE;

}

return uncut;

}//ConCat

截断不仅在求联接串发生,在其他操作中如插入、置换等也可能发生,要克服这个弊病,惟有不限定串长的最大长度,即动态分配串值的存储空间。

2.串的堆分配存储表示

以一组地址连续的存储单元存放串值字符序列,但它们的存储空间是在程序执行过程中动态分配而得。所以也称为动态存储分配的顺序表。在C语言中,利用malloc()和free()等动态存储管理函数,来根据实际需要动态分配和释放字符数组空间。

---------串的堆分配存储表示---------

typedef struct{

char *ch;

//若是非空串,则按串长分配存储区;否则ch为NULL

int length; //串长度

}HString;

通常,C语言中提供的串类型就是以这种存储方式实现。系统利用动态分配函数malloc()和free()进行串值空间的动态管理,为每一个新生成的串分配一个存储区,称串值共享的存储空间为“堆”,C语言中的串以一个空字符为结束符,串长是一个隐含值。

82903cb41be8b642db63632403cb9f2b.png

StrInsert(Hstring &S,int pos,Hstring T){ //在串s中序号为

//pos的字符之前插入串t

if (pos<1 || pos>s->len) return ERROR;

//1≤pos≤StrLength(S) +1, 注意:pos是逻辑定义的下标

if(T.length){ //T非空

if(!(S.ch=(char*)realloc(S.ch, (S.length+T.length)*sizeof(char))))

exit(OVERFLOW);

for(i = S.length-1; i>pos-1; i--) //为插入T而腾出位置

S.ch[i + T.length] = S.ch[i];

S.ch[pos – 1 .. pos + T.length – 2] = T.ch[0.. T.length – 1]; //插入T

/* pos -1 + (T.length – 1)  pos + T.length – 2*/

S.length += T.length;

}

return OK

}//StrInsert

3.串的块链存储表示

串值也可以用链表来存储,由于串的数据元素是一个字符,它只有8位二进制数,因此用链表存储时,通常一个结点中存放的不是一个字符,而是一个子串。

存储密度=串值所占的存储位/实际分配的存储位

存储密度小,运算处理方便,但存储占用量大,在进行串处理过程中,内外存交换频繁,影响处理效率。

为了提高存储密度,可使每个结点存放多个字符。通常将结点数据域存放的字符个数定义为结点的大小,显然,当结点大小大于1时,串的长度不一定正好是结点的整数倍,因此要用特殊字符来填充最后一个结点,以表示串的终结。

对于结点大小不为1的链串,其类型定义为只需对上述的结点类型做简单的修改即可。

typedef struct Chunk{

char ch[CHUNKSIZE];

struct Chunk *next;

}Chunk;

typedef struct{//串的链表结构

Chunk *head, *tail;

int curlen;

}LString;

37c3c34117a9f6276763a1077ac4d563.png

4.3 串的模式匹配

模式匹配:子串定位运算称为模式匹配(Pattern Matching)或串匹配(String Matching)。

模式匹配成功是指在目标串s中找到一个模式串t;

模式匹配不成功则指目标串s中不存在模式串t。

主要讨论串的简单模式匹配算法,采用顺序存储结构。

在串匹配中,一般将主串称为目标串,子串称为模式串。设S为目标串,T为模式串,设:

S=“s0s1s2…sn-1”

T=“t0t1…tm-1”

回顾串匹配(查找)的定义:

Index(S,T,pos)

初始条件:串S和T存在,T是非空串。

操作结果:若主串S中存在和串T值相同的子串,则返回它在主串S中第pos个字符之后第一次出现的位置,否则函数值为0 。

1、简单算法

基本思想:从目标串s的第一个字符起和模式串t的第一个字符比较,若相等则继续逐个比较后续字符,否则从串s的第二个字符起再重新和串t进行比较。依此类推,直至串t中的每个字符依次和串s的一个连续的字符序列相等,则称模式匹配成功,此时串t的第一个字符在串s 中的位置就是t 在s中的位置,否则模式匹配不成功。

假设s=“cddcdc”,t=“cdc”,则模式匹配过程如下:

6e44cccb0d70654cab2379fc64dc7913.png

简单算法的C语言描述如下:

int Index(SString S,SString T, int pos){

//返回子串T在主串S中第pos个字符之后的位置,若不存在,则函数值为0,其中,T非空,(1≦pos≦Strlength(S))。

i=pos; //指向串s的第pos个字符

j=1; //指向串t的第1个字符

while((i<=S[0])&&(j<=T[0])){

if(S[i]==T[j]) { ++i; ++j; } //继续比较后继字符

else {i=i-j+2; j=1;} //串S指针回溯重新开始匹配

}

if(j>T[0]) return i-T[0];

//匹配成功,返回模式串t在串s中的起始位置

else return 0; //匹配失败返回0

} //Index

2、首尾匹配算法

先比较模式串的第一个字符,

再比较模式串的最后一个字符,

最后比较模式串中从第二个到第n-1个字符

具体算法不再详细讨论。

3、KMP算法

074a1ffced05d7bee7fdb2bb5cca68d3.png

6485dbaf31d284a4e80c3d41aa403118.png

835b875e52e33d8ff03f09c4e1721f0c.png

0be5af0f3232a8c5af23f3bcba731af6.png

7385832ffaf35a7da01eb0c124e8fc98.png

2365a692d030046493c4ad3415705137.png

5e79e241411bcde2ebc34b92e798d97a.png

标签:子串,字符,存储,串值,pos,length,数据结构,第四章

来源: https://blog.csdn.net/weixin_42260102/article/details/99577162

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值