数据结构(串,数组和广义表)
4.1串的定义
串(字符串),是由多个字符组成的线性表,是一种内容受限的线性表
串长:串中字符的个数
空串:零个字符的串
子串:串中任意个连续的字符组成的子序列。包含字串的串相应称为主串
真子串:不包含本身的子串
空格串:由一个或多个空格组成的串
字串位置:子串中第一个字符在主串中出现的位置
串相等:两个串的长度相同并且各个位置的字符都相同
4.3串的类型定义,存储结构及其运算
4.3.1串的抽象数据类型定义:p89
4.3.2串的存储结构
串的存储结构包括顺序存储结构和链式存储结构
一.串的顺序存储结构(使用更多)
类型定义:
#define MAXSIZE 255 //设置串的最大长度
typedef struct
{char ch[MAXSIZE+1]; //存储串的一维数组。多数情况下,串的下标从1开始,下标为0的位置闲置int length; //故设置空间为MAXSIZE+1
}SString;
一般情况下,为了便于操作,串的下标为0的位置闲置,从下标为1的位置开始存储
二.串的链式存储结构
字符占1type,二指针占4type,如果每个字符都只占一个结点,那么存储密度过小。因此采用块链结构存储链串
结构示意图:
类型定义:
#define chunksize 80; //块的最大长度typedef struct Chunk //定义块
{char Chunk[chunksize]; //每个块所存储的字符的空间Chunk *next; //指向下一个块的指针
}Chunk;typedef struct //定义链串
{Chunk *head,*tail; //头尾指针int length; //串当前的长度
}LString;
4.3.3串的模式匹配算法
子串的定位运算通常称为串的模式匹配或串匹配。一般将主串S称为正文串,将子串T称为模式串。该算法即在主串中查找子串
一.BF算法(暴力破解)
算法4.1BF算法
算法步骤:1.分别利用指针i和j指示主串S和模式串T当前正待比较的字符位置,i初值为pos,j初值为1
2.如果两个串均未到达串尾,即i和j分别小于S和T的串长时,则循环执行:
*1.S.ch[i]和T.ch[j]比较,如果相等,则都指向下一位置
*2.如果不相同,指针后退重新匹配,从主串的下一字符(i = i - j + 2)起再重新和模式串第一个字符比较
3.如果j>T.length,说明匹配成功,返回字串位置(i-T.length),否则失败,返回0
关于(i = i-j+2)的解释:i = i - j + 2是i从当前位置减去已经匹配过j次的长度j,回到最初的位置,然后再+1到下一位置重新匹配(+2————i-j+1+1,从下标1开始存储)
算法描述:
int Index_BF(SString S,SString T,int pos)(1<=pos<=S.length)
{int i = pos,j = 1; //j表示模式串匹配位置,i表示文本串匹配位置while(i<=S.length&&j<=T.length) //循环条件{if(S.ch[i]==T.ch[j]) //比较两串{i++,j++; //如果匹配成功,则两者均后移继续匹配}else //如果匹配失败,i和j都要回溯,i要回到开始的下一位,j从头{i=i-j+2,j = 1;}}if(j>T.length) //匹配成功,返回字串位置return i - T.length;else //匹配失败,返回0return 0;
}
算法分析:设m和n分别为子串和主串长
最好情况下,平均时间复杂度为O(m+n)
最坏情况下,平均时间复杂度为O(m*n)
算法4.2KMP算法(下标从1开始)
前缀:包含首字母,不包含尾字母的所有子串
后缀:包含尾字母,不包含首字母的所有子串
最长相等前后缀:某个字符前(不包含本身)的子串的最长的相等的前后缀长度
前缀表:模式串中每个字符其前的最长相等前后缀的长度组成的顺序表
设文本串"aabbaabbaaf',模式串"aabbaaf"
主串 | a | a | b | a | a | b | a | a | f | |
子串 | a | a | b | a | a | f | ||||
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
前缀表 | 0 | 1 | 2 | 1 | 2 | 3 |
如上图匹配过程中,找出与f前的后缀相等的前缀的后一位继续匹配,其下标即是最长相等前后缀的长度加1,即f对应的前缀表
next数组:用来存储前缀表的数组
手算next数组:规定next[1] = 0,next[2] = 1;
next[j]:模式串中第j位字符的前j-1位字符组成的子串的最长相等前后缀长度+1(下标从1开始),也是匹配冲突时需要回溯的下标值
next数组的代码实现
void GetNext(SString T,int next[])
{int i = 1,j = 0; //设置初始比较位置next[0] = 0; //初赋值while(i < T.length) //循环条件{if(j==0||T.ch[i]==T.ch[j]) //找最大相对前后缀,每有一个前缀字符和后缀字符相等,最大{ //数+1,并填入当前位置的前缀表,ij同时后移比较下一个next[++i]=++j; }else j = next[j]; //如果不同,相当于j回溯比较,再跟之前的比,找前后缀}
}
算法4.2KMP算法
算法描述:
int KMPindex(SString S,SString T,int pos)
{int i = pos,j = 1; //i表示主串开始查找的位置,j表示模式串开始比较的位置while(i<=S.length&&j<=T.length) //条件{if(j==0||S.ch[i]==T.ch[j]) //如果匹配成功{i++,j++; //后移继续匹配}else //匹配失败j = next[j]; //模式串回溯到前缀表指示的位置(相当于模式串右移,相等前} //缀跑到相等后缀的位置继续比较if(j>T,length) //匹配成功return i-T.length;else //匹配失败return 0;
}
4.4数组
4.4.1数组的类型定义
数组是由类型相同的数据元素构成的有序集合,每个元素称为数组元素
一维数组可以看成是一个线性表,二维数组可以看成数据元素是线性表的线性表
二维数组的逻辑结构:非线性结构:每个数据元素即在行表中,也在列表中
线性结构:该线性表的每个元素依然是线性表
三维数组:二维数组中的元素又是一维数组
n维数组:n-1维数组中的元素又是一个一维数组
数组一旦被定义,它的维数和维界就不再改变。因此除了初始化和销毁之外,数组只有存取元素和修改元素的操作。
结论:线性表是数组结构的特例,数组结构是线性表的拓展
4.4.2数组的顺序存储
由于数组一般不做插入或删除操作,因此采用顺序存储结构表示数组比较合适
由于存储单元是一维结构,而数组可能是多维结构。则用一组连续存储单元存放数组元素就有约定次序的问题(即多维关系如何映射到一维关系)
①:以行序为主序的存储方式
②:以列序为主序的存储方式
由此,对于数组,一旦规定了其维数和维界,便可为其分配空间。反之,只要给出一组下标便可求出相应数组元素的存储位置:
一维数组:
(i为前面元素个数,L为每个元素所占空间)
二维数组:
(前i行都填满了,j为本行前有多少元素)
三维数组a[m1][m2][m3]:
以此类推
4.4.3特殊矩阵的压缩存储
在数值分析中经常出现阶数很高的矩阵,同时矩阵中有很多值相同的元素或0元素。为了节约存储空间,可以对这类矩阵进行压缩存储。
压缩存储:多个值相同的元只分配一个存储空间,对零元不分配空间
假若相同的元素或零元素在矩阵中的分布有一定规律,或0元多。则称此类矩阵为特殊矩阵,主要包括:对称矩阵,三角矩阵,对角矩阵,稀疏矩阵等。
1.对称矩阵
对称矩阵中的元满足以下特性
1<=i,j<=n
对于对称矩阵,可以为每一对对称元分配一个存储空间。则可将n^2个元压缩到n(n-1)/2个元的空间中,以行序为主序存储其下三角(包括对角线)中的元。
假设以一维数组sa[n * (n - 1) / 2]作为n阶对称矩阵A的存储结构,则sa[k]和矩阵元a_{i,j}存在一一对应的关系如下:
ps:前有i行,共i(i-1)/2个元素,加上本行前j-1个元素
k = 0,1,2....n(n+1)/2-1
2.三角矩阵
以主对角线划分,三角矩阵有上三角矩阵和下三角矩阵。上三角矩阵是指矩阵下三角(不包括对角线)中的元均为常数c或0的n阶矩阵。下三角矩阵与之相反。
对三角矩阵进行压缩存储,除了和对称矩阵一样,再加一个存储常数c的存储空间即可
(1)上三角矩阵
sa[k]和矩阵元aij之间的关系为
(2)下三角矩阵
sa[k]和矩阵元aij之间的关系为
3.对角矩阵
对角矩阵的所有非零元都集中在以对角线为中心的带状区域中。也可按某个规则(或以行为主,或以对角线为主的顺序)压缩到一个一维数组上
例:以对角线存储(二维数组)
结果为
4.稀疏矩阵
稀疏矩阵:在m*n的矩阵中有t个非零元,设
若 则称该矩阵为稀疏矩阵
稀疏矩阵的存储方法有:三元组法,十字链表法
(1)三元组法
三元组(i,j,aij)和矩阵维数m*n——唯一确定矩阵中的一个非零元
压缩存储原则:存各非零元的值,行列位置和矩阵行列数。
三元组的不同表示方法可以决定稀疏矩阵不同的压缩存储方法。
注:为更可靠的描述信息,通常再加一个总体信息:总行数,总列数,总非零元个数(通常存放在0下标位置)
优点:非零元在表中按行序有序存储,便于进行依行序顺序处理的运算
缺点:不能随机存取,若按行号查找某一行中的非零元,需从头查找
(2)十字链表法
优点:灵活地插入因运算产生的新非零元素,删除因运算产生的新0元,实现各种运算
结点结构:
例:对于矩阵
其十字链表结构为:
4.5广义表
4.5.1广义表的定义
LS = (a1,a2....an)
LS是广义表表名,n是表长,ai称为元素。元素既可以是单个元素(原子),也可以是广义表(子表)。习惯上大写字母表示广义表,小写字母表示原子。
表头:广义表的第一个元素,可以是单原子,也可以是子表
表尾:取出除了表头以外的元素构成的表。表尾一定是广义表
例: A = ()——长度为0,深度为1
B = (e)——只有一个原子e,长度为1,深度为1,表头为e,表尾为()
C = (a,(b,c,d))——长度为2,深度为2,表头为a,表尾为((b,c,d))
D = (A,B,C)——D = ((),(e),(a,(b,c,d)))——长度为3,深度为3,表头为()
表尾为((e),(a,(b,c,d)))
E = (a,E)——E = (a,(a,(a,....)))——长度为2,深度无穷,表头为a,表尾为(E)
F = (())——长度为1,深度为2,表头表尾均为()
广义表的性质:
(1)广义表中元素有相对次序,一个直接前趋,一个直接后继
(2)广义表长度定义为最外层括号包含的元素个数
(3)广义表深度定义为该广义表展开后所含括号的重数
注:原子深度为0,空表深度为1
(4)广义表的元素可以是子表,子表的元素还可以是子表......。所以广义表是一个多层次的 结构
(5)广义表可为其他广义表共享:即广义表的元素是另一个广义表
(6)广义表可以是一个递归的表,即广义表可以是本身的一个子表
数据结构(串,数组和广义表)相关推荐
- [数据结构与算法] 串,数组和广义表
串偏向于算法,数组和广义表偏向于理解 第四章 串.数组和广义表 4.1 串的定义 4.2 案例引入 4.3 串的类型定义,存储结构及运算 4.3.1 **串的类型定义** 4.3.2 串的存储结构 4 ...
- 数据结构05数组和广义表
第五章 数组 和 广义表 数组和广义表可以看成是线性表在下述含义上的扩展:表中的数据元素本身也是一个数据结构. 5.1 数组的定义 n维数组中每个元素都受着n个关系的约束,每个元素都有一个直接后继元素 ...
- 数据结构之数组与广义表
目录 联系 数组 广义表 联系 数组和广义表可看作一种扩展的线性数据结构,其特殊性在于数据元素的构成上.从组成线性表的元素角度看,数组是由具有某种结构的数据元素构成,广义表则是由单个元素或子表构成的. ...
- 数据结构:数组和广义表
数组 数组这部分内容在写<线性表>的的时候介绍过,所以这里就略过一部分内容(略过的内容在这里),写一写前边没写过的. 由于数组中各元素具有统一的类型,并且数组元素的下标一般具有固定的上界和 ...
- C语言数据结构学习——数组和广义表
数组和广义表 数组 数组定义 特点 常见运算及声明方式 数组的顺序表示和实现 矩阵的压缩存储 概念 稀疏矩阵 对称矩阵 三角矩阵 广义表 数组 数组定义 数组(Array)是有序的元素序列.若将有限个 ...
- 六、考研数据结构笔记——数组与广义表
一.数组的定义 一维数组:就是线性表,前面有 二维数组:准备考研的应该都知道,就是一个矩阵. 数组一旦被定义其,维数(行)和维界(列)就不能改变.只会读取加修改元素. 二.二维数组的按行(列)优先 事 ...
- 【数据结构】数组和广义表
感觉数组这一段没讲什么太多的东西. 先是讲了下定义,就是每个维度上都有对应的前驱后继,首尾元素例外.操作只有初始化 销毁 取元素 修改元素.然后讲了下适合用顺序存储结构,多维情况下根据下标(j1 j2 ...
- 【数据结构总结】第四章:串、数组和广义表(线性结构)
第四章:串.数组和广义表(线性结构) 提示:本文主要是以思维导图的形式概括数据结构第一章的精华内容,基本不会用到文字性的内容,目的是为了给大家梳理每个重要的知识点的相关概念,方便大家在复盘的时候快速阅 ...
- 《数据结构》-第四章 串、数组和广义表(习题)
第四章 串.数组和广义表练习题 本章考点较少易于掌握,对于串的重点考点为串的模式匹配算法:数组的主要考点为数组下标与存储地址计算和特殊矩阵的压缩存储方法:针对广义表的考点主要为在广义表中取原子项(表) ...
- 数据结构:串、数组和广义表
串 线性结构:线性表.栈和队列.串与数组和广义表 串的逻辑结构和线性表极为相似,区别仅在于串的数据对象限定为字符集.在基本操作上,串和线性表有很大差别.线性表的基本操作主要以单个元素作为操作对象,如查 ...
最新文章
- TCP三次握手和四次挥手图示
- 使用Windows Server2012或R2 DHCP故障转移群集需要注意的几点
- Javascript中的\r\n
- Karush-Kuhn-Tucker (KKT条件)
- QT学习:多线程控制
- boost::to_address用法实例
- python xlrd课程_python中xlrd模块的使用详解
- Android之Animation动画的介绍及用法
- 多域名解析及延伸知识点
- 会玩!今年天猫双11可以买房了 还是特价 网友:满300减40吗?
- vue标准时间改为时间戳_2021考研网上确认照片采集新标准公布 网上确认时间表...
- windowForm资料
- 实战演习(九)——用python分析科比生涯数据
- 城市和经纬度一致性验证
- 程序员知道什么叫劳务外包?企业为什么要选择劳务外包吗?
- PS用圆角矩形工具画出来的是实线而是虚线,哪里出问题了?
- 2022考研笔记-政治(思修)
- NC15979 小q的数列
- 关于Win10与Ubuntu18.04的装机教程与疑问解答
- Android Activity的隐式调用(跨进程)★