3.串,数组,广义表——数据结构 (严蔚敏C语言版)

串,数组,广义表

串的定义

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

在这里插入图片描述
子串: 一个串中任意个连续字符组成的子序列(含空串)称为该串的子串。
主串: 包含子串的串相应地称为主串。
字符位置: 字符在序列中的序号为该字符在串中的位置。
子串位置: 子串第一个字符在主串中的位置。
空格串: 由一个或多个空格组成的串,与空串不同。

:字符串a、b、c、d
a= D,
b= ‘JING'
C=‘BEIJING'
d=‘BEI JING'
------------
它们的长度是:3 4 7 8
c的子串是:a b
d的子串是:a b
a在c中的位置是:1
a在d中的位置是:1
b在c中的位置是:4
a在d中的位置是:

串的结构

逻辑结构

1.链式存储:链串
2.顺序存储:顺序串

  • 顺序存储结构(更常用)
#define MAXLEN 255
typedef struct{
	char ch[MAXLEN+1];//存储串的一维数组
	int length;//串的当前长度长度
}SString;
  • 链式存储结构

在这里插入图片描述
优点: 操作方便
缺点: 存储密度较低

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

解决办法:可将多个字符存放在一个结点中,以克服其缺点。

在这里插入图片描述

//串的链式存储结构---块链结构

#define CHUNKSIZE 80//块的大小可由用户定义
typedef struct Chunk{
	char ch[CHUNKSIZE];
	struct Chunk *next;
}Chunk;


typedef struct{
	Chunk *head,*tail;		//串的头指针和尾指针
	int curlen;				//串的当前长度
}LString;
//字符串的块链结构

串的操作

串的模式匹配

算法目的:
确定主串中所含子串(模式串)第一次出现的位置(定位)
算法应用:
搜索引擎、拼写检查、语言翻译、数据压缩
算法种类:

  • BF算法(Brute-Force,又称古典的、经典的、朴素的、穷举的)
  • KMP算法(特点:速度快,难理解)
1.BF算法

算法思想:
将主串的第n个字符和模式串的第一个字符比较,

  1. 若相等,继续逐个比较后续字符;
  2. 若不等,从主串的下一字符起,重新与模式串的第一个字符比较。

i=i-j+2 (回溯) (i:主串的位置)
j=1 (从头开始) (j:子串的位置)

  • 直到主串的一个连续子串字符序列与模式串相等。返回值为S中与T匹配的子序列第一个字符的序号,即匹配成功。
  • 否则,匹配失败,返回值0。
//算法的思路是从S的每一个字符开始依次与T的字符进行匹配。
S:a a a a b c d			主串:正文串
T:a b c					子串:模式

在这里插入图片描述

时间复杂度

则算法复杂度O(n*m)
比较差

2.KMP算法

算法思想

利用已经部分匹配的结果而加快模式串的滑动速度;且主串S的指针i不必回溯!时间复杂度可提速到 O(n+m)

可直接找next[j],它它表明当模式串中第j个字符与主串中相应字符不匹配时,在模式串中 ,需要和主串中该字符串进行比较的位置。

在这里插入图片描述
重要的例1
在这里插入图片描述

//KMP算法
int Index_KMP (SString s,SString T, int pos){
	i= pos,j =1;
	while (i<S.length && j<T.length) {
			if (j==0 || S.ch[i]==T.ch[j]){ i++; j++; }
			else j = next [j];//i不变,j后退
		}
	if (j>T.length) return i-T.length;/*匹配成功*/
	else return 0;/*返回不匹配标志*/
}

//计算next函数值
void get_next(SString T, int &next[]){
	i= 1; next[1] = o; j = O;
	while( i<T.length){
			if(j==O || T.ch[i] == T.ch[j]){
				++i; ++j;
				next[i] = j;
			}
		else
		j = next[j];
	}
}

重要的例2

根据next求nextval的值

模式串abaabcac
next值01122312
nextval值01021302

具体过程:
1.第一位的nextval值必定为0,第二位如果于第一位相同则为0,如果不同则为1。
2.第三位的next值为1,那么将第三位和第一位进行比较,均为a,相同,则第三位的nextval值为第一位的next值,为0。
3.第四位的next值为2,那么将第四位和第二位进行比较,不同,则第四位的nextval值为其next值,为2。
4.第五位的next值为2,那么将第五位和第二位进行比较,相同,第二位的next值为1,则继将第二位与第一位进行比较,不同,则第五位的nextval值为第二位的next值,为1。
5.第六位的next值为3,那么将第六位和第三位进行比较,不同,则第六位的nextval值为其next值,为3。
6.第七位的next值为1,那么将第七位和第一位进行比较,相同,则第七位的nextval值为0。7.第八位的next值为2,那么将第八位和第二位进行比较,不同,则第八位的nextval值为其next值,为2。

数组

数组的定义

数组: 按一定格式排列起来具有相同类型的数据元素的集合。

1.一维数组:

若线性表中的数据元素为非结构的简单元素,则称为一维数组。

一维数组的逻辑结构: 线性结构。定长的线性表。

声明格式:

数据类型 变量名称 [长度];
例: int num[5] = 10, 1,2,3,4};

2.二维数组:

若一维数组中的数据元素又是一维数组结构,则称为二维数组。在这里插入图片描述

二维数组的逻辑结构

  • 非线性结构:每一个数据元素既在一个行表中,又在一个列表中。
  • 线性结构:该线性表的每个数据元素也是一定长的线性表。

二维数组的存储
二维数组可有两种存储方式:

  • 以行序为主序;
  • 以列序为主序。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

以行序为主序:
设数组开始存储位置LOC( 0,0),存储每个元素需要L个存储单元数组元素 a[i][j]的存储位置是:LOC( i , j)= LOC(0,0)+(n*i+j)*L,也就是在a[i][j]前面所有元素个数。

总结

  • 线性表结构是数组结构的一个特例,而数组结构又是线性表结构的扩展。
  • 数组特点: 结构固定——定义后,维数和维界不再改变。
  • 数组基本操作: 除了结构的初始化和销毁之外,只有取元素和修改元素值的操作。

注意: 数组可以是多维的,但存储数据元素的内存单元地址是一维的,因此,在存储数组结构之前,需要解决将多维关系映射到一维关系的问题。

例,有数组定义: int a[5];
每个元素占用4字节,假设a[0]存储在2000单元,a[3]地址是多少?

特殊矩阵的压缩存储

  • 1.什么是压缩存储?
    若多个数据元素的值都相同,则只分配一个元素值的存储空间,且零元素不占存储空间。
  • 2.什么样的矩阵能够压缩?
    一些特殊矩阵,如:对称矩阵,对角矩阵,三角矩阵,稀疏矩阵等。
  • 3.什么叫稀疏矩阵?
    矩阵中非零元素的个数较少(一般小于5%)
1.对称矩阵

特点: 在nxn的矩阵a中,满足如下性质:aij=aji (1 ≤i, j sn)
存储方法: 只存储下(或者上)三角(包括主对角线)的数据元素。共占用n(n+1)/2个元素空间。

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

2.三角矩阵

特点: 对角线以下(或者以上)的数据元素(不包括对角线)全部为常数c。
存储方法: 重复元素c共享一个元素存储空间,共占用n(n+1)/2+1个元素空间: sa[1… n(n+1)/2+1]。

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

3.对角矩阵

特点: 在nxn的方阵中,所有非零元素都集中在以主对角线为中心的带状区域中,区域外的值全为0,则称为对角矩阵。常见的有三对角矩阵、五对角矩阵、七对角矩阵等。

下图:一个7x7的三对角矩阵
在这里插入图片描述

例:
一个五对角矩阵, 以对角线顺序存储。
在这里插入图片描述
在这里插入图片描述

4.稀疏矩阵

有顺序存储和链式存储两种

1.三元组顺序表(顺序存储)

压缩存储原则:存各非零元的值、行列位置和矩阵的行列数。

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

注意:为更可靠描述,通常再加一个“总体”信息:即总行数、总列数、非零元素总个数(上图的 6 7 8)。

  • 三元组顺序表的优点:非零元在表中按行序有序存储,因此便于进行依行顺序处理的矩阵运算。
  • 三元组顺序表的缺点:不能随机存取。若按行号存取某一行中的非
    零元,则需从头开始进行查找。

2.十字链表(链式存储)

  • 优点:它能够灵活地插入因运算而产生的新的非零元素,删除因运算而产生的新的零元素,实现矩阵的各种运复
  • 在十字链表中,矩阵的每一个非零元素用一个结点表示,该结点除了(row,col,value)以外,还要有两个域:

right: 用于链接同一行中的下一个非零元素; down: 用以链接同一列中的下一个非零元素。

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

广义表

广义表的定义

  • 广义表通常记作:Ls= (a, , …,an)
    其中:LS为表名,n为表的长度,每一个ai为表的元素。
  • 习惯上,一般用大写字母表示广义表,小写字母表示原子。
  • 表头:若LS非空(n≥1),则其第一个元素a就是表头。
    记作 head(LS)= a1。
    注:表头可以是原子,也可以是子表。
  • 表尾:除表头之外的其它元素组成的表。
    记作tail(LS= (2 … an)。
    注:表尾不是最后一个元素,而是一个子表。

例:p103

  1. 广义表中的数据元素有相对次序;一个直接前驱和一个直接
  2. 广义表的长度定义为最外层所包含元素的个数;
    如:C=(a, (b, c))是长度为2的广义表。
  3. 广义表的深度定义为该广义表展开后所含括号的重数;
    A =(b, o)的深度为1,B=(A,d)的深度为2,C=(f, B, h)的深度为3。注意:“原子”的深度为0;“空表”的深度为1。
  4. 广义表可以为其他广义表共享;如:广义表B就共享表A
    在B中不必列出A的值,而是通过名称来引用,B= (A)。
  5. 广义表可以是一个递归的表。如:F=(a,F)=(a, (a, (a…)))
    注意:递归表的深度是无穷值,长度是有限值。
  6. 广义表是多层次结构,广义表的元素可以是单元素,也可以
    是子表,而子表的元素还可以是子表。
    可以用图形象地表示。
    例:D=(EF)
    其中:E=(a, (b,c))
    F=(d, (e))
广义表基本运算
  • 求表头GetHead(L):非空广义表的第一个元素,可以是一个单原子,也可以是一个子表
  • 求表尾GetTail(L):非空广义表除去表头元素以外其它元素所构成的表。表尾一定是一个广义表

例1:p103

例2:在这里插入图片描述

广义表的存储

1.头尾链表存储
2.扩展线性表存储
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值