数据结构与算法学习笔记 串,数组和广义表

Posted 临风而眠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法学习笔记 串,数组和广义表相关的知识,希望对你有一定的参考价值。

数据结构与算法学习笔记(6) 串、数组和广义表

截图、笔记来自: 王卓 数据结构与算法

一.串

1.串的定义

  • 串:零个或多个任意字符组成的有限序列

  • 几个术语

    • 子串:串中任意个连续字符组成的子序列称为该串的子串
      • 真子串是不包含自身的所有子串
    • 主串: 包含子串的串相应地称为主串
    • 字符位置:字符在序列中的序号为该字符在串中的位置
    • 子串位置: 子串第一个字符在主串中的位置
    • 空格串:由一个或多个空格组成的串,与空串不同
    • 串相等: 当且仅当两个串的长度相等且在各对应位置上字符都相同时,这两个串才相等
      • 注意所有空串都相等

2.串的类型定义、存储结构及其运算

串的类型定义

串的存储

串的顺序存储结构
#define MAXLEN 255
typedef struct{
	char ch[MAXLEN+1];	//存储串的一维数组
    					// 0号单元存放串的长度
	int length;	//串的当前长度
}SString;
串的链式存储结构

根据需要选择单链表/双向链表/循环链表等

  • 优点:操作方便

  • 缺点:存储密度低

  • 解决办法

    将多个字符放在一个结点中,以克服其缺点

块链结构

上述解决办法就是块链结构

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

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

顺序存储结构用的更多,因为匹配查找运算用的多,删除插入用的少

3.串的模式匹配算法

  • 算法目的:

    确定主串中所含子串(模式串)第一次出现的位置(定位)

  • 算法应用

    搜索引擎、拼写检查、语言翻译、数据压缩

  • 算法种类

    • BF算法(Brute-force,古典的、经典的、朴素的、穷举的)
    • KMP算法(速度快)

①BF算法

  • 例子引入

    • 对i-j+2的理解

      T从1位置移动到j,移动了j-1个长度,则S也移动了j-1

      S现在的位置是i,移动的长度也是j-1,用现在的位置i减去移动的长度i-(j-1),再加1就是下一个位置,所以是i-j+2

  • 算法思想

  • 算法描述

    int Index_BF(SString S,SString T){
    	int i=1,j=1;
    	while(i<=S.length && j<=T.length){
    	//j>T.length时说明j的每个字符都匹配成功了,就不用继续匹配了
    	 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;	//模式匹配不成功
    }
    

    or

    int Index(SString S, SString T, int pos) {
         i = pos;   j = 1;
        while (i <= S[0] && j <= T[0]) {
          if (S[i] == T[j]) { ++i;  ++j; }   // 继续比较后继字符
          else
          { i = i-j+2;   j = 1; }                  // 指针后退重新开始匹配
        }
       if (j > T[0])  return  i-T[0];
       else return 0;
    } // Index
    
  • 算法时间复杂度分析

    • 最坏时间复杂度:

      在最坏情况下,每趟不成功的匹配都发生在模式串T的最后一个字符

      那么前n-m趟不成功的匹配比较了(n-m)*m次,最后一趟匹配成功比较了m次,则总共匹配了(n-m)*m+m

②KMP算法

这里听了一遍没理解,去搜了搜别的教程,推荐几个:

👉有个哈工大师兄在B站发的视频讲的挺好

👉天勤辉哥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]=0; j=0;
    	while(i<T.length){
    		if(j==0||T.ch[i]==T.ch[j]){
    			++i;++j;
    			next[i]=j;
    		}
    		else
    			j = next[j];
    	}
    }
    

二.数组

1.数组的定义及特点

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

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

    • 一维数组的逻辑结构:线性结构
      • 是定长的线性表
    • 声明格式
    数据类型 变量名称[长度];
    
  • 二维数组

    二维数组既可以看成线性结构,也可以看成非线性结构

    • 声明格式

      数据类型	变量名称[行数][列数];
      
    • array1是有n个元素的一维数组

  • 三维数组

  • 数组特点:结构固定

    ​ 定义后,维数和维界不再改变

  • 数组基本操作

    插入删除等操作会破坏数组结构

2.数组的抽象数据类型定义

  • n维数组的抽象数据类型

    n n n为数组的维数, b i b_i bi为数组第i维的长度, j i j_i ji为数组元素第i维的下标

3.数组的顺序存储结构

  • 一维数组

  • 二维数组

    • 以行序为主序

    • 以列序为主序

      • 二维数组的行序优先表示

  • 三维数组

  • n维数组

4.特殊矩阵的压缩存储

①对称矩阵的压缩存储

②三角矩阵、对角矩阵的压缩存储

  • 三角矩阵

空间里面那个+1是用来存储常数c

  • 对角矩阵

③稀疏矩阵的压缩存储

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

    • 三元组的不同表示方法可决定稀疏矩阵不同的压缩存储方法
三元组顺序表

  • 优缺点

    下面的十字链表可以克服三元组顺序表的缺点

稀疏矩阵的链式存储结构:十字链表

三.广义表

广义表也是递归定义

线性表中的元素是同类型的单一元素

上面说的原子就是指单一元素

  • 广义表的一些基本概念

  • 广义表的性质

  • 广义表和线性表的区别

  • 广义表的基本运算

以上是关于数据结构与算法学习笔记 串,数组和广义表的主要内容,如果未能解决你的问题,请参考以下文章

数据结构 第4章 串数组和广义表 单元小结重点 BF算法

第四章心得体会

数据结构(C语言版) 串数组和广义表 算法设计Demo6

数据结构(C语言版) 串数组和广义表 算法设计Demo1

数据结构第四章总结

数据结构与算法学习笔记串和数组