王卓老师课程的听课笔记
串(String)是由零个或多个任意字符组成的有限序列
串的内容称之为串值,串的名称称为串名
当元素大小等于0时,被称为空串,用空集的符号表示,空串连空格都没有。
子串:一个串中任意个连续字符组成的子序列(含空串),称为该串的子串。
真子串是指不包含自身的所有子串
主串:包含子串的串相应地称为主串
字符位置:字符在序列中的序号为该字符在串中的位置
字串位置:子串第一个字符在主串中的位置
空格串:由一个或多个空格组成的串,与空串不同
串相等:当且仅当两个串长度相等并且各个对应位置上的字符都相同时,这两个串才相等,空串全部都相等
串的顺序存储结构
#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算法
主串S(正文串),子串T(模式串)
BF算法代码:
int Index_BF(SString S,SString T) { int i = 1,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;//模式匹配不成功 }
课本算法源码
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;//模式匹配不成功 }
int Index KMP(SString S,SString T,int pos) { i = pos,j = i; 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[j]的算法
void get_next(SString T,int &next[]) { i = 1;next[1] = 0;j = 0; while(i<T.length) { if(j == 0||T.ch == T.ch[j]) { ++i; ++j; next[i] = j; } else { j = next[j]; } } }
针对next函数的改进
如果前面出现了很多相同的字符,字符本身没有匹配上,那么后面也不需要重复的对已经失配的字符城府匹配了。
void get_nextval(SString T,int &nextval[]) { i = 1;nextval[1] = 0;j = 0; while(i<T.length) { if(j==0||T.ch[i] == T.ch[j]) { ++i; ++j; if(T.ch[i] != T.ch[j]) { nextval[i] = j; } else { nextval[i] = nextval[j]; } } else j = nextval[j]; } }
按照一定的格式排列起来的,具有相同类型的数据元素的集合。
若线性表中的数据元素为非结构的简单元素,则称为一维数组。
一维数组的逻辑结构:线性结构。定长的线性表。
声明格式:数据类型 变量名称[长度];
可以单个赋值,也可以统一初始化赋初值。
二维数组:若一维数组中的数据元素又是一维数组结构,则称为二维数组
二维数组的逻辑结构
声明格式:数据类型 变量名称[行数] [列数];
在C语言中,一个二维数组类型也可以定义为一维数组类型(其分量类型为一维数组类型),即:
typedef elemtype array2[m][n]; //等价于: typedef elemtpye array1[n]; typedef array1 array2[m];
三维数组:若二维数组中的元素又是一个一维数组,则称作三维数组。
n维数组:若n-1维数组中的元素又是一个一维数组结构,则称作n维数组。
线性表结构是数组结构的一个特例,而数组结构又是线性表结构的扩展。
数组特点:结构固定——定义后,维数和维界不再改变。
数组基本操作:除了结构的初始化和销毁之外,只有取元素和修改元素值的操作。
二维数组在内存中如何存储呢?
C,PASCAL,Java,Basic,是以行序为主序(一行一行来存储)
个别语言以列序为主序
设数组开始存储位置LOC(0,0),存储每个元素需要L个存储单元,数组元素a[i] [j]的存储位置是:LOC(i,j) = LOC(0,0) + (n*i+j) *L
三维数组,按页/行/列存放,计算地址位置同理二维数组。
矩阵的常规存储:
将矩阵描述为一个二维数组
矩阵的常规存储的特点:
不适宜常规存储的矩阵:值相同的元素很多,且呈某种规律分布;零元素多。
矩阵的压缩存储:为多个相同的非零元素只分配一个存储空间;对零元素不分配空间。
什么是压缩存储?
若多个数据元素的值都相同,则只分配一个元素值的存储空间,且零元素不占存储空间。
什么样的矩阵能够压缩?
一些特殊矩阵,如:对称矩阵,对角矩阵,三角矩阵,稀疏矩阵等。
什么叫稀疏矩阵?
矩阵中非零元素的个数较少(一般小于5%)
对称矩阵
存储时可以以行序为主序储存下三角
按顺序存储到一维数组当中
又称List,是n>=0个元素的有限序列,其中每一个元素,可以是任何形式的数据。
广义表通常记作LS = (a1,a2,a3…,an)
其中:LS为表名,n为表的长度,每一个ai为表的元素。
习惯上,一般用大写字母表示广义表,小写字母表示原子。
表头:若LS非空,则第一个元素a1就是表头。记作head(LS) = a1.表头可以是原子,也可以是子表。
表尾:除表头之外的其他元素组成的表。
记作 tail(LS) = (a2,…,an)
注:表尾不是最后一个元素,而是一个子表。
广义表中的数据元素有相对次序:一个直接前驱和一个直接后继
广义表的长度定义为最外层所包含元素的个数;
广义表的深度定义为该广义表展开后所含括号的重数;
广义表可以为其他广义表共享。
广义表可以是一个递归的表,长度有限,深度无限。
广义表是多层次结构,广义表的元素可以是单元素,也可以是子表,而子表的元素还可以是子表…
广义表可以看成是线性表的推广,线性表是广义表的特例