第四章 串、数组和广义表

一、串的定义和实现

1.串的定义

串——零个和任意多个字符组成的有限序列称为串。

计算机上非数值处理的对象基本都是字符串
串相等:串长度相等,对应位置字符都相等。

2.串的顺序存储

类似于线性表的顺序存储结构,用一组地址连续的存储单元存储串值的字符序列。按照预定义的大小,为每个预定义的串变量分配一个固定长度的存储区。

#define MAXLEN 255
typedef struct{
	char ch[MAXLEN+1];
	int length;
}SString;

3.串的链式存储

顺序串的插入和删除操作不方便,需要移动大量的字符。因此,可采用单链表方式存储串。由于串结构的特殊性——结构中的每个数据元素是一个字符,则在用链表存储串值时,存在一个“结点大小”的问题,即每个结点可以存放一个字符,也可以存放多个字符。

//串的链式存储
#define CHUNKSIZE 80  //可由用户定义块的大小
typedef struct Chunk{
	char ch[CHUNKSIZE];
	struct Chunk *next;
}Chunk;
typedef struct
{
	Chunk *head,*tail;//串的头指针和尾指针
	int length;   //串的当前长度

}LString;

但是链式存储有点是操作方便,缺点就是存储密度较低。为了克服这个缺点,可以将多个字符存放在一个结点中。

4.串的模式匹配算法

4.1BF算法

【算法思路】
①将主串的第pos个字符与模式串的第一个字符进行比较:
     若相等,继续逐个比较后续字符;
     若不等,从主串的下一个字符开始,重新与模式串的第一个字符进行比较。
②直到主串的一个连续字符串字符序列与模式串相等。返回值为S中与T匹配的子序列的第一个字符的序号,即匹配成功。否则,匹配失败。

【算法步骤】
① 分别利用计数指针i和j指示主串S和模式T中当前正待比较的字符位置,i初值为pos,j初值为1。
② 如果两个串均未比较到串尾,即i和j均分别小于等于S和T的长度时,则循环执行以下操作:
·S.ch[i]和T.ch[j]比较,若相等,则i和j分别指示串中下个位置,继续比较后续字符;
·若不等,指针后退重新开始匹配,从主串的下一个字符(i=i-j+2)起再重新和模式的第一个字符(j=1)比较。
③ 如果j>T.length,说明模式T中的每个字符依次和主串S中的一个连续的字符序列相等,则匹配成功,返回和模式T中第一个字符相等的字符在主串S中的序号(i-T.length);否则称匹配不成功,返回0。

【算法描述】

//返回模式T在主串S中第pos个字符开始第一次出现的位置。若不存在,则返回值为0
int Index_BF(SString S,SString T,int pos)
{
	int i=pos,j=1;//初始化
	while(i<=S.length&&j<=T.length)//两串均未比较到串尾
	{
		if(S.ch[i]==T.ch[j])      //继续比较后续字符
		{
			i++;
			j++;
		}
		else                       //指针后退,重新开始匹配
		{
			i=i-j+2;             
			j=1;
		}	
	}
	if(j>T.length)
		return i-T.length;//匹配成功,返回匹配的第一个字符下标
	else
		return 0;         //匹配失败
}

【时间复杂度】
暴力匹配算法最坏的时间复杂度为O(n*m)

【优点和缺点】
优点:算法思路清晰明了
缺点:总是回溯到i-j+2的位置,模式串总是恢复到首字符位置j=1,因此算法时间复杂度高。

4.1 KMP算法

KMP算法较BF算法在算法效率上有了很大的提高。其改进在于:当一趟匹配过程中出现字符比较不等时,不需回溯i指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离后,继续进行比较。
【时间复杂度】
O(m+n)

二、数组

1.数组的定义

【定义】数组是由n个(n>=1)相同类型的数据元素构成的有限序列。
【二维数组】若一维数组中的数据元素又是一维数组结构,则称二维数组。
线性表结构是数组结构的一个特例,而数组结构又是线性表结构的拓展。
【注意】数组是多维的,但存储数的内存单元地址是一维的,因此,在存储数组结构之前,需要解决将多维关系映射到一维关系的问题。

2.数组的顺序存储

【数组特点】 结构固定——维数和维界不变
【数组基本操作】 结初始化、销毁、取元素、修改元素值。一般不做插入删除

3.二维数组的存储方式

行序为主


列序为主

3.特殊矩阵的压缩存储

所谓压缩存储就是指为多个值相同的元只分配一个存储空间,对零元不分配空间。

3.1对称矩阵
3.2三角矩阵
3.3三对角矩阵

4稀疏矩阵

【定义】
矩阵中非零元素的个数t,相对矩阵个数s来说较少。

【压缩存储原则】
存储各非零元素的值,行列位置和矩阵行列数

【存储方法】
三元组、十字链表法

【三元组顺序表的优点】
非零元素在表中按行有序存储,便于尽进行依行顺序处理的矩阵运算,又称有序的双下表法。

【三元组顺序表的缺点】
不能随机存取。若按行号取某一行的非零元素,则需从头开始查找。

【十字链表的优点】
它能够灵活的插入因运算而产生的新的非零元素,删除因运算而产生的新的零元素,实现矩阵的各种运算。

三、广义表

1.广义表的定义

广义表(又称列表Lists)是n>=0个元素的有限序列,其中每一个元素或者是原子,或者是广义表。
广义表是线性表的推广
广义表是个递归的概念
表头:第一个元素
表尾:除表头之外的其他元素组成的表

2.广义表的性质

①广义表中的数据元素有相对次序,一个直接前驱,一个直接后继。
②广义表的长度定义为最外层所包含元素的个数
③广义表的深度定义为该广义表展开后所包含括号的重数
④广义表可以为其它广义表共享。
⑤广义表可以是一个递归的表。递归的深度是无穷值,长度是有限值
⑥广义表是多层次结构,广义表的元素可以是单元素,也可以是子表

3.广义表与线性表的区别

广义表可以看做是线性表的推广,线性表是广义表的特例。
当二维数组的每行或者每列作为子表处理时,数组即为一个广义表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值