4.2串的顺序存储结构

4.2串的顺序存储结构

1、定长顺序串

定长顺序串是将串设计成一种静态结构类型,串的存储分配是在编译时完成的。与前面所讲的线性表的顺序存储结构类似,可用一组地址连续的存储单元存储串的字符序列。

1)定长顺序串存储结构

定长顺序串类型定义如下:

#define MAXLEN 40 
typedef struct 
{      /*串结构定义*/ 
	char ch[ MAXLEN]; 
	int len; 
}SString; 

其中 MAXLEN 表示串的最大长度,ch 是存储字符串的一维数组,每个分量存储一 个字符, len 是字符串的长度。

2)定长顺序串基本操作的实现

( 1 )串插入函数

问题分析

在进行顺序串的插入时,插入位置 pos 将串分为两部分(假设为 A、 B,长度为 LA、 LB)及待插入部分(假设为 C,长度为 LC),则串由插入前的 AB 变为 ACB,由于是顺序串, 插入会引起元素的移动。

可能出现以下三种情况:

  • ①插入后串长( LA+LC +LB)≤ MAXLEN,则将 B 后移 LC 个元素位置,再将 C 插入。
  • ②插入后串长>MAXLEN 且 pos+LC≤ MAXLEN,则 B 后移时会有部分字符被舍弃。
  • ③插入后串长> MAXLEN 且 pos +LC >MAXLEN,则 B 的全部字符被舍弃(不需后移),并 且 C 在插入时也有部分字符被舍弃。

算法描述

StrInsert(SString *s, int pos, SString t) 
/*在串 s 中下标为 pos 的字符之前插入串 t */ 
{ 
	int i; 
	if (pos<0 || pos>s->len) 
		return(0); /*插入位置不合法*/ 
	if (s->len + t.len<=MAXLEN) 
	{   /*插入后串长≤MAXLEN*/     
		for (i=s->len + t.len-1;i>=t.len + pos;i--)      
			s->ch[i]=s->ch[i-t.len];     
		for (i=0;i<t.len;i++) 
			s->ch[i+pos]=t.ch[i];       
		s->len=s->len+t.len;     
	} 
	else if (pos+t.len<=MAXLEN) 
	{/*插入后串长>MAXLEN,但串 t 的字符序列可以全部插入*/     
		for (i=MAXLEN-1;i>t.len+pos-1;i--) 
			s->ch[i]=s->ch[i-t.len];     
		for (i=0;i<t.len;i++) 
			s->ch[i+pos]=t.ch[i];     
		s->len=MAXLEN;     
	} 
	else 
	{  /*插入后串长>MAXLEN,并且串 t 的部分字符也要舍弃*/
		for (i=0;i<MAXLEN-pos;i++) 
			s->ch[i+pos]=t.ch[i];     
		s->len=MAXLEN;     
	} 
	return(1); 
} 

显然,实现顺序串插入的算法其实现复杂度为: O( s->len+t.len)。

( 2 )串删除函数
StrDelete(SString *s, int pos, int len) 
/*在串 s 中删除从下标 pos 起 len 个字符*/ 
{ 
	int i; 
	if (pos<0 || pos>(s->len-len)) 
		return(0);   /*删除参数不合法*/ 
	for (i=pos+len;i<s->len;i++)    
		s->ch[i-len]=s->ch[i]; 
	/*从 pos+len 开始至串尾依次向前移动,实现删除 len 个字符*/ 
	s->len=s->len - len; 
	/*s 串长减 len*/ 
	return(1); 
} 
(3)串的简单模式匹配 Brute-Force(布鲁特-福斯)算法

算法思想
简单的模式匹配算法是一种带回溯的匹配算法,算法的基本思想是:从主串 S 的第 pos 个字符开始,和模式串 T 的第一个字符开始比较,如果相等,就继续比较后续字符, 如果不等,则从(回溯到)主串 S 的第 pos+1 个字符开始重新和模式串 T 比较,直到模式串 T 中 的每一个字符和主串 S中的一个连续字符子序列全部相等,则称匹配成功,返回和 T 中第一个 字符相等的字符在主串 S 中的位置;或者主串中没有和模式串相等的字符序列,则称匹配不成功。

算法描述
实现时设 i、 j、 start 三个指示器:
i——指向主串 S 中当前比较的字符,起始指向 S 的首字符,此后,每比较一步,后移一步,一 趟匹配失败时,回溯到该趟比较起点的下一位置。
j———指向子串T中当前比较的字符,起始指向T的首字符,此后,每比较一步,后移一步, 一趟匹配失败时,回溯到 T 的首字符处。
start———记录每趟比较时在主串 S 中的起点,每趟比较后,后移一步,以便确定下一趟的起始位置。

在这里插入图片描述
在这里插入图片描述

顺序串的简单模式匹配(定位)函数
StrIndex(SString s,int pos, SString t)  
/*求从主串 s 的下标 pos 起,串 t 第一次出现的位置,成功返回位置序号,不成功返回-1*/ 
{ 
	int i, j, start; 
	if (t.len==0)  
		return(0);   /* 模式串为空串时,是任意串的匹配串 */ 
	start=pos;  
	i=start;  
	j=0;  /* 主串从 pos 开始,模式串从头(0)开始 */ 
	while (i<s.len && j<t.len)     
		if (s.ch[i]==t.ch[j]) 
		{
			i++; 
			j++;
		}   /* 当前对应字符相等时推进 */ 
		else 
		{ 
			start++;        /* 当前对应字符不等时回溯 */ 
			i=start;  
			j=0;   /* 主串从 start+1 开始,模式串从头(0)开始*/ 
		}  
	if (j>=t.len) 
		return(start);    /* 匹配成功时,返回匹配起始位置 */ 
	else 
		return(-1);    /* 匹配不成功时,返回-1 */ 
} 

算法分析
该算法思路比较简单,但最坏时间复杂度较高,为 O( s.len* t.len),如主串为 51 个 0 ,模式串为 7 个 0 后有个 1 ,每趟都在最后一个不匹配后而倒到 start+1 ,整个匹配过程 共需 s.len- t.len=45 趟,每趟比较 t.len=8 个字符,故此例整个比较了 360 次。这个算法的主要时间耗费在失配后的比较位置有回溯,造成了比较次数太多的情况。降低时间复杂度可采用无回溯的算法

2、堆串

字符串包括串名与串值两部分,而串值采用堆串存储方法存储,串名用符号表 存储。

堆串存储方法:仍以一组地址连续的存储单元顺序存放串中的字符,但它们的 存储空间是在程序执行过程中是动态分配的。系统将一个地址连续、容量很大的 存储空间作为字符串的可用空间,每当建立一个新串时,系统就从这个空间中分配 一个大小和字符串长度相同的空间存储新串的串值。

串名符号表:所有串名的存储映像构成一个符号表。借助此结构可以在串名和串值之间建立一个对应关系,称为串名的存储映像。
在这里插入图片描述

1)堆串存储表示:

C 语言已经有一个称为“堆”的自由存储空间,并可用函数 malloc()和函数 free()完成动态存储管理。

因此,可以直接利用 C 语言中的“堆” 来实现堆串。此时堆串可定义如下:

typedef struct 
{ 
	char * ch; 
	int len; 
}HString;  

其中 len 域指示串的长度,ch 域指示串的起始地址。

2)堆串基本操作的实现

( 1 )堆串插入函数
StrInsert(HString *s,int pos,HString *t) 
/*在串 s 中下标为 pos 的字符之前插入串 t */ 
{ 
	int i; 
	char *temp; 
	if (pos<0 || pos>s->len || s->len==0) 
		return(0); /*插入位置不合法*/ 
	temp=(char *)malloc(s->len + t->len); /*动态产生足够的空间存放插入后的串*/ 
	if (temp==NULL) 
		return(0); 
	for (i=0;i<pos;i++) 
		temp[i]=s->ch[i]; 
	for (i=0;i<t->len;i++) 
		temp[i+pos]=t->ch[i]; 
	for(i=pos;i<s->len;i++)
		temp[i + t->len]=s->ch[i]; 
	s->len+=t->len; 
	free(s->ch); 
	s->ch=temp; 
	return(1); 
} 
( 2 )堆串删除函数
StrDelete(HString *s,int pos,int len) 
/*在串 s 中删除从下标 pos 起 len 个字符 */ 
{ 
	int i; 
	char *temp; 
	if (pos<0 || pos>(s->len - len)) 
		return(0); /*删除参数不合法*/ 
	temp=(char *)malloc(s->len - len); 
	if (temp==NULL) return(0); 
	for (i=0;i<pos;i++) 
		temp[i]=s->ch[i]; 
	for (i=pos;i<s->len - len;i++) 
		temp[i]=s->ch[i+len]; 
	s->len=s->len-len; 
	free(s->ch); 
	s->ch=temp; 
	return(1); 
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值