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

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

相关文章

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

C语言:柔性数组

数组定义 柔性数组 err int arr[0] = {0}; // ERROR 柔性数组 // 常见struct Test{int len;char arr[1024];} // 柔性数组struct Test{int len;char arr[0];}struct Test *t;t = malloc(sizeof(Test) + 11);strcpy(t->arr,

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou