数据结构 第四章 串、数组和广义表

2024-06-22 18:38

本文主要是介绍数据结构 第四章 串、数组和广义表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

概述:

串:字符串的简称,串是一种特殊的线性表,特殊在其数据元素都是一个字符。
数组和广义表可以看做是线性表的扩充,即线性表的数据元素自身又是一个数据结构。

串 String

本结主要讲述:串的存储结构和基本操作
定义:主要是有0个或多个字符组成的序列。
存储结构:顺序存储和链式存储,但是串一般使用顺序存储结构。

顺序存储

typedef struct {char *ch;   //若为非空串,则按串长分配存储区,否则ch为nullint length;  //串长度
}HString;

链式存储:

#define CHUNKSIZE 80;  //可有用户定义的块大小
typedef struct Chunk{char ch[CHUNKSIZE ];   struck Chunk *next;
}Chunk;typedef struct {Chunk *head,*tail;//串的头尾指针int  curlen;   //串的当前长度
}LString;

串的存储密度=串值所占的存储位/实际分配的存储位
密度小,运算处理才方便;

串的模式匹配算法
子串的定位运算通常称为串的模式匹配或串匹配。
应用场景:搜索引擎、拼音检查、语言翻译、数据压缩等。

eg:有两个字符串S-主串、T-子串(也称模式);
著名的模式匹配算法有两种:BF和KMP算法:
1. BF算法:最简单直观的模式匹配算法,Brute-Force算法

int Indext(SString S,SString T,int pos){int i=pos,j=1;  //i指向主串,j指向子串while(S[0]>=i && 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;}}

主串长:N ,子串长:M
算法的时间复杂度:在最好的情况下(N+M)1/2即O(N+M),最坏的情况下:M(N-M+2)*1/2即O(N+M);
BF思路直观简明,但是时间复杂度高为:O(N+M),

2.KMP算法:由Kunth Morris Pratt共同设计所以称为KMP算法;
特点:无需回溯主串的指针,当模式串与主串中存在许多“部分匹配”的情况下才显得比BF快,所以BF至今任然被采用。
时间复杂度:O(m+n)

int Indext_KMP(SString S,SString T,int pos){//利用模式串Tnext函数求T在主串S中第pos个字符之后的位置//其中,T非空,1<=pos<=Strlength(S)int i=pos,j=1;  //i指向主串,j指向子串while(S[0]>=i && j<=T[0]){if(j==0 || S[i] == T[j]){++i;++j;}else{j=next[j]; //模式串向右移动 }}if(j>T[0]){return i-T[0];}else{return 0;}}T的Next函数,算法时间复杂度为O(m)
void get_next(SString T,int next[]){int i = 1;next[1] = 0 ;int j = 0 ;while(i<T[0]){if(j == 0 || T[i] == T[j]){++i;++j;next[i] = j;}else{j=next[j];}}
}
J12345678
模式串abaabcac
next[j]01122312

上面的next算法有缺陷,下面有修正版的:void get_nextval(SString T,int nextval[]){int i = 1;nextval[1] = 0 ;int j = 0 ;while(i<T[0]){if(j == 0 || T[i] == T[j]){++i;++j;if(T[i] != T[j]){nextval[i] = j;}else{nextval[i] = nextval[j];}}else{j=nextval[j];}}
}

next函数修正值:

J12345
模式串aaaab
next[j]01234
nextval[j]00004

数组

本结主要讲述:数组的内部实现和特殊的二维数组如何实现压缩存储。
定义:由类型相同的数据元素构成的有序集合。

一维数组可以看成线性表
二维数组是数据元素为线性表的线性表;
数组一般不做插入和删除操作,所以一般采用顺序存储结构。

二维数组有两种存储方式:列序为主序的存储方式,行序为主序的存储方式。
java、C、Basic、Pasical都是行序为主序的编程语言;
Fortran是以列序为主序的编程语言;

每个元素占L个存储单元,二维数组A[0~m-1,0~n-1](A[m,n])中任一元素aij的存储位置:
LOC(i,j)=LOC(0,0)+(n x i+j)L;

由于计算各个元素存储位置的时间相等,所以存取数组中任一元素的时间也相等,即数组是一种随机存取结构。


矩阵的压缩存储

矩阵用二维数组来表示是最自然的。
压缩存储:指为多个值相同的元只分配一个存储空间,对0元不分配空间;
特殊矩阵:对值相同的元素或0元素在矩阵中的分布有一定规律;
主要有三种特殊矩阵:对称矩阵、三角矩阵、对角矩阵
若n阶矩阵A中的元满足Aij=Aji,称为n阶对称矩阵。
–可将n2个元素压缩到n(n+1)/2个元的空间中。
设一维数组Sa[n(n+1)/2]作为矩阵A的存储结构,则sa[k]和矩阵元aij的关系:
k=i(i-1)/2+j-1 条件(i < j)
k=j(j-1)/2+i-1 条件(i > j)


广义表

本结主要讲述:广义表的概念和存储结构。
广义表是线性表的推广,也称为列表。
广泛的用于人工智能领域的表处理语言LISP语言。
记为:LS=(a1,a2,a3,a4…..an)

//广义表的头尾链表存储表示
typedef enum{ATOM,LIST
}ElemTag;typedef struct GLNode{ElemTag tag;   union{AtomType atom;struct{struct GLNode *hp;struct GLNode *tp;}ptr;};
}*GList;

这篇关于数据结构 第四章 串、数组和广义表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1085093

相关文章

【数据结构】线性表:顺序表

文章目录 1. 线性表2. 顺序表2.1 概念及结构2.2 接口实现2.3 顺序表的问题及思考 1. 线性表 线性表是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式

数据结构9——排序

一、冒泡排序 冒泡排序(Bubble Sort),顾名思义,就是指越小的元素会经由交换慢慢“浮”到数列的顶端。 算法原理 从左到右,依次比较相邻的元素大小,更大的元素交换到右边;从第一组相邻元素比较到最后一组相邻元素,这一步结束最后一个元素必然是参与比较的元素中最大的元素;按照大的居右原则,重新从左到后比较,前一轮中得到的最后一个元素不参4与比较,得出新一轮的最大元素;按照上述规则,每一轮结

剑指offer(C++)--数组中只出现一次的数字

题目 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 class Solution {public:void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {int len = data.size();if(len<2)return;int one = 0;for(int i

IOS 数组去重的几种方式

本来只知道NSSet和KeyValues的。今天又新学了几种方式 还有就是和同事学的一种方式 外层循环从0开始遍历,内层从最后一个元素开始遍历 for(int i=0;i<index;i++){  for(int j=index-1;j>i;j-- ){ } }

算法与数据结构面试宝典——回溯算法详解(C#,C++)

文章目录 1. 回溯算法的定义及应用场景2. 回溯算法的基本思想3. 递推关系式与回溯算法的建立4. 状态转移方法5. 边界条件与结束条件6. 算法的具体实现过程7. 回溯算法在C#,C++中的实际应用案例C#示例C++示例 8. 总结回溯算法的主要特点与应用价值 回溯算法是一种通过尝试各种可能的组合来找到所有解的算法。这种算法通常用于解决组合问题,如排列、组合、棋盘游

嵌入式学习——数据结构(哈希、排序)——day50

1. 查找二叉树、搜索二叉树、平衡二叉树 2. 哈希表——人的身份证——哈希函数 3. 哈希冲突、哈希矛盾 4. 哈希代码 4.1 创建哈希表 4.2  5. 算法设计 5.1 正确性 5.2 可读性(高内聚、低耦合) 5.3 健壮性 5.4 高效率(时间复杂度)时间复杂度越低,效率越高, 5.5 低储存(空间复杂度)空间复杂度越低,存储空间越少 6.排序算法 6.1 冒

【数据结构与算法 经典例题】使用队列实现栈(图文详解)

💓 博客主页:倔强的石头的CSDN主页               📝Gitee主页:倔强的石头的gitee主页    ⏩ 文章专栏:《数据结构与算法 经典例题》C语言                                   期待您的关注 ​​ 目录  一、问题描述 二、前置知识 三、解题思路 四、C语言实现代码 🍃队列实现代码:

数据结构:二叉树详解 c++信息学奥赛基础知识讲解

目录 一、二叉树的定义 二、二叉树的形态 三、二叉树的性质 四、二叉树的存储 五、二叉树的创建与遍历(递归) 六、二叉树实现 创建二叉树 展示二叉树 1、计算数的高度 2、计算数的叶子数量 3、计算数的宽度 4、层次遍历 5、前序遍历 递归写法 非递归写法 6、中序遍历 递归写法 非递归写法 7、后序遍历 递归写法 非递归写法 8、输出根节点到所有叶

Java基础(二)——数组,方法,方法重载

个人简介 👀个人主页: 前端杂货铺 ⚡开源项目: rich-vue3 (基于 Vue3 + TS + Pinia + Element Plus + Spring全家桶 + MySQL) 🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步至千里,积小流成江海 🥇推荐学习:🍖开源 rich-vue3 🍍前端面试

Java数据结构4-链表

1. ArrayList的缺陷 由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置插入和删除比较多的场景。因此:java集合中又引入了LinkedList,即链表结构。 2. 链表 2.1 链表的概念及结构 链表是一种物理存储结构上非连续存储结构,数据元素