数据结构(已完结)

绪论


第一部分 线性表

一、顺序表

注意:线性表中的位序是从1开始,而数组中的元素下标从0开始。

储存:一定连续

时间复杂度:O(1)

基本操作1:初始化

基本操作2:取值

基本操作3:按值查找

二、链表

存储:非顺序

时间复杂度:O(n)

两类:带头结点和不带头结点

带头结点单链表为空:


L->next==NULL;

不带头结点单链表为空:


L==NULL;

基本操作1:初始化

基本操作2:取值

基本操作3:插入

基本操作4:删除


第二部分 栈和队列

栈的表尾为栈顶,栈的表头为栈顶。只允许栈顶元素出入栈。先进后出,后进先出。

队列只允许在队尾删除,在队顶插入。先进先出,后进后出。  

顺序栈

注意:top指向栈顶元素后一位。  


S.top==0 //栈空  

S.top==maxsize //栈满  

基本操作1:初始化

基本操作2:入栈

基本操作3:出栈

基本操作4:顺序取栈顶元素

栈的操作是线性表操作的特例。

队列

链式存储与线性表类似

循环队列

需要附设front和rear两个指针表示队头和队尾。

注意:

1.front指向队头,rear指向队尾的后一个元素。

2.队列空和队列满时,front和rear都指向同一结点。  

如何判断队列是空是满?

1.少用一个元素空间。

2.另设一个标志位。

基本操作1:定义储存结构

基本操作2:初始化

基本操作3:求长度

基本操作4:插入新元素

基本操作5:删除元素


第三部分 串、数组、广义表

储存方式:定长顺序存储、堆分配存储、块链存储

1.定长顺序存储:预定义数组长度,为每个串分配固定长度的存储区。

-1.1显式存储串长。

–1.1.1以下标为0的数组分量存放(数组)。

–1.1.2专设一个字段(结构体)。

-1.2隐式存储串长。

2.堆分配存储:一组地址连续的存储单元,但存储空间是动态分配。

3.串的块链存储:采用链式存储。一个结点可以存储多个字符。结点的字符个数就是结点大小。

数组

数组是线性表的推广,特点是结构中的元素本身可以是具有某种结构的数据,但属于同一数据类型。

一维数组:看作线性表或向量。适合随机查找。

二位数组:看作矩阵。不是线性表,是线性表的推广。

广义表

线性表的推广。可以在广义表里面嵌套广义表。

**长度:**包含数据元素个数。

**深度:**匹配最多括号的元素的括号层数。

第四部分 树和二叉树

树和二叉树

树的定义:

树是一种非线性的数据结构,它是由n个有限结点组成有层次关系的集合。

树的特点:

每个结点具有0个或多个子结点

每个子结点只有一个父结点

没有前驱的结点为根结点

除了根结点外,每个子结点又可以由m棵不相关的子树组成

树的基本术语:

1.结点的度:结点拥有的子树数量称为结点的度

2.树的度:树内各结点度的最大值,即上图 D 结点的度就是此树的度

3.叶子:度为 0 的节点称为叶子或终端节点

结点的层次和树的深度

4.森林:m棵互不相交的树的集合

*二叉树的性质:

性质1:在二叉树的第i层上至多有2i-1个结点(i>=1)。

性质2:深度为k的二叉树至多有2k-1个结点(k>=1)。

性质3:对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则 n 0 n_0 n0 = n 2 + 1 n_2+1 n2+1

性质4:具有n个结点的完全二叉树的深度为 ⌊ l o g 2 n ⌋ + 1 ⌊log_2n⌋ + 1 log2n+1

性质5:如果对一颗有n个结点的完全二叉树(其深度为 ⌊ l o g 2 n ⌋ + 1 ⌊log_2n⌋ + 1 log2n+1)的结点按层序编号(从第1层到第 ⌊ l o g 2 n ⌋ + 1 ⌊log_2n⌋ + 1 log2n+1 层,每层从左到右),对任一结点i(1<=i<=n)有:

a.如果i=1,则结点i是二叉树的根,无双亲;b.如果i>1,则其双亲是结点 ⌊ i / 2 ⌋ ⌊i/2⌋ i/2

c.如果 2i>n ,则结点 i 无孩子(结点i为叶子结点);否则其左孩子是结点 2i;

d.如果 2i+1>n ,则结点 i 无右孩子;否则其右孩子是结点 2i+1。*

二叉树的存储:顺序(通常用于完全二叉树)、链式

*二叉树的遍历方法:先序、中序、后序、层序

1.先序:

访问根结点–先序遍历左子树–先序遍历右子树(根左右)

2.中序:

中序遍历左子树–访问根结点–中序遍历右子树(左根右)

3.后序:

后序遍历左子树–后序遍历右子树–访问根结点(左右根)

4.层序:

按层次(1-k层),每层从左到右依次访问二叉树中的每一个结点。*

哈夫曼树

基本概念:

1.路径:从一个结点到另一个结点之间的分支序列。

2.​路径长度:从一个结点到另一个结点所经过的分支数目。

3.​结点的权:根据应用的需要可以给树的结点赋权值。

4.​结点的带权路径长度:从根到该结点的路径长度与该结点权的乘积。

5.​树的带权路径长度:树中所有叶子结点的带权路径之和 ∑ k = 1 n w k ∗ l k \sum_{k=1}^nw_k*l_k k=1nwklk

6.​哈夫曼树:由n个带权叶子结点构成的所有二叉树中带权路径长度最短的二叉树。

注意:

1.n个叶子结点的哈弗曼树有 2n-1 个结点。

2.在构造哈弗曼树时,是从叶子结点向根节点的方向进行的,每次都是两个两个成对的结点来形成一个新的分支结点,所以不存在度为1的结点。

哈夫曼树的构造

对于有n个叶子结点,可以构造出多个二叉树。

但Huffman树是一个带权路径长度最小的二叉树,又称最优二叉树

方法:

(1)将{w1,w2,…….,wn}看成n个二叉树;

(2)选择 2 个根结点的值最小(权值最小)的二叉树,构造1个新的二叉树;…….;直至剩1个树止。

哈夫曼编码

前缀码:

如果在一个编码系统中,任一个编码都不是其他任何编码的前缀,则称该编码系统中的编码是前缀码。例如,一组编码01,001,010,100,110就不是前缀码,因为01是010的前缀,若去掉01或010就是前缀码。

哈夫曼编码:

对一棵具有n个叶子的哈夫曼树,若对树中的每个左分支赋予0,右分支赋予1,则从根到每个叶子的通路上,各分支的赋值分别构成一个二进制串,该二进制串就称为哈夫曼编码。


第六部分 图

图的定义与基本术语

图G由顶点集V和边集E组成,记为G=(V,E),其中V(G)表示图G中顶点的有限非空集;E(G)表示图G中顶点之间的关系(边)的集合。

注意:线性表可以是空表,树可以是空树,图不可以是空图,图可以没有边,但是至少要有一个顶点。

有向图

若E是有向边(简称弧)的有限集合时,则G为有向图。弧是顶点的有序对,记为<v,w>,其中 v,w 是顶点。当v 是弧尾,w 是弧头时,称为从顶点v到顶点w的弧。

无向图

若E是无向边(简称边)的有限集合时,则G为无向图。边是顶点的无序对,记为 (v,w) 或(w,v) ,且有 (v,w) =(w,v) 。其中 v,w 是顶点。

完全图

1.无向图中任意两点之间都存在边,称为无向完全图;如G1就是无向完全图。无向完全图具有 n(n-1)/2 条边。

2.有向图中任意两点之间都存在方向向反的两条弧,称为有向完全图;有向完全图具有 n(n-1)条弧。

子图:

设两个图G=(V, E)和G’=(V’,E’),如果V’⊆V且 E’ ⊆E,则称G’为G的子图。

顶点的度、入度和出度

顶点的度为以该顶点为一个端点的边的数目

对于无向图,顶点的边数为度,度数之和是顶点边数的两倍。

对于有向图,入度是以顶点为终点(即箭头所指方向),出度是以顶点为起点 (即箭尾巴所指方向)。

有向图的全部顶点入度之和等于出度之和且等于边数。顶点的度等于入度与出度之和。

注意:入度与出度是针对有向图来说的。

路径:

在图 G=( V, E ) 中, 若从顶点 x 出发, 经过一些顶点v1, v2, …… , vm到达顶点y。 则称顶点序列 ( x ,v1, v2, … Vm, y ) 为从顶点x 到顶点 y 的路径。

路径长度 :

非带权图的路径长度是指此路径上边的条数。

带权图的路径长度是指路径上各边的权之和。

简单路径:

序列中顶点不重复出现的路径。

回路(环):

第一个顶点和最后一个顶点相同的路径。

简单回路(环):

除第一个和最后一个顶点,其余顶点不重复出现的路径。

图的存储结构:邻接矩阵

图的邻接矩阵的存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息(可分别称他们为顶点数组和边数组)。

在无向图中,求某个顶点的度,即计算此顶点 v i v_i vi在邻接矩阵中第i行(或第i列)的元素之和。若 v i v_i vi v j v_j vj之间有通路,则记为1,反之为0。

在有向图中,求某个顶点vi的出度,即求此顶点所在行的元素之和,若求某个顶点的度,即求顶点所在列的元素之和。

设图G有n个顶点,则邻接矩阵是一个n×n的方阵A。

邻接矩阵表示法的优缺点

优点:

便于判断两个顶点之间是否有边, 即根据A[i] [j] = 0或1来判断。

便于计算各个顶点的度。对于无向图,邻接矩阵第 i 行元素之和就是顶点 i 的度;对于有向图,第 i 行元素之和就是顶点 i 的出度,第 i 列元素之和就是顶点 i 的入度。

缺点:

不便于增加和删除顶点。

不便于统计边的数目,需要扫描邻接矩阵所有元素才能统计完毕,时间复杂度为 O( n 2 n^2 n2)

空间复杂度高。

图的存储结构:邻接表

对图中的每个顶点建立一个单链表,存储该顶点所有邻接顶点及其相关信息。每一个单链表设有一个表头结点。把从一个顶点出发的所有边链接在一个单链表(又名边链表)中。把所有边链表的表头结点放在一个顺序表(又名顶点表)中。

邻接表表示法的优缺点

优点

便于增加和删除结点

便于统计边的数目

空间效率高

缺点

不便于判断顶点之间是否有边

不便于计算有向图各个顶点的度(需要遍历)

图的遍历

深度优先、广度优先

深度优先搜索

思想:类似先序遍历。

广度优先搜索

思想:由近及远,类似层序遍历。

图的应用:拓扑排序


第七部分 查找

顺序查找

查找第i个元素需要的次数:n-i+1

要查找的元素不在表中:n+1

平均查找长度(ASL)=(n+1)/2

时间复杂度O(n)=(n+1)/2

折半查找

三个指针:low,high,middle

low,high,middle全部指向的元素即为所求

ASL= l o g 2 ( n + 1 ) − 1 log_2(n+1)-1 log2(n+1)1

时间复杂度O(n)= l o g 2 n log_2n log2n

索引查找(分块查找)

块与块间必须有大小关系

要点:索引查找表

ASL:

内部顺序查找: 1 2 ( n s + s ) + 1 {1 \over 2 }({n \over s}+s)+1 21(sn+s)+1

内部折半查找: l o g 2 ( n s + 1 ) + s 2 log_2({n\over s}+1)+{s\over2} log2(sn+1)+2s


第八部分 排序

内排序、外排序

排序方法

一、插入排序

1.直接插入排序:稳定?稳定!

时间复杂度 O ( n ) = n 2 O(n)=n^2 O(n)=n2

2.折半插入排序

3.2-路插入排序

前面三种方法都不可避免的要移动记录

4.表插入排序(希尔排序)

算法思想:每趟取步长成子表排序,下一趟步长为上次的一半(向下取整),直到1。

时间复杂度 O ( n ) = n 1.3 O(n)=n^{1.3} O(n)=n1.3

特点:不移动记录。

增量序列:

eg:5,3,1

表示数据先每间隔5分成1组,再每间隔3分成1组,以此类推。

二、交换排序

1.冒泡排序(稳定)

排序次数:至多n-1次,至少1次

方法:从后两两对比,更小的往前放。

2.快速排序(不稳定)

算法思想:

a.通过快速排序,把待排序记录分成独立的两组。其中,一组的关键字均比另一组小。

b.采用同样的方法,对一趟快速排序产生的两个子序列进行快速排序。

c.递归执行a和b,直到子序列的记录个数为1。

*口诀:

小放枢轴左,大放枢轴右。

高低所指换,换针向枢轴。

高低所遇处,枢轴所落入。

递归再排至,左右仅一头。*

排序次数C(n): C ( n ) = n − 1 + C ( k ) + C ( n − k − 1 ) C(n)=n-1+C(k)+C(n-k-1) C(n)=n1+C(k)+C(nk1)

时间复杂度O(n): O ( n ) ≤ n ∗ l o g 2 n O(n)\le n*log_2n O(n)nlog2n

三、选择排序

基本思想:

每次从当前待排序的记录中选取“关键字第i(i=1,2,…,n)小的记录”, 放置在记录序列的位置i,直到所有n个记录都有序为止。

1.简单选择排序

时间复杂度 O ( n ) = n 2 O(n)=n^2 O(n)=n2

思想:先扫,再找,放入最前。

拓展:树形选择排序和堆排序

a.树形选择排序

思想:

i.借助“淘汰赛”中的对垒过程,对关键字序列进行排序。

该过程可用一棵有n个叶子结点的 完全二叉树表示。每个分枝结点的关键字都等于其左&右孩子结点中较小的关键字,根结点的关键字就是最小的关键字。

ii.输出最小关键字后,根据关系的可传递性,欲选取次小关键字,只需:

将叶子结点中的最小关键字 改为“最大值(inf)”;

然后,重复上述步骤即可。

b.堆排序(不稳定)

时间复杂度O(n)= n ∗ l o g 2 n n*log_2n nlog2n

空间复杂度S(n)=O(1)

思想:

i.对一组待排序的记录,按堆的定义建立堆。

ii.将堆顶记录和最后一个记录交换位置,则前n-1个记录是无序的,而最后一个记录是有序的。

iii.堆顶记录被交换后,前n-1个记录不再是堆,需将前n-1个待排序记录重新组织成为一个堆;然后,将堆顶记录和倒数第二个记录交换位置,即将整个序列中次小关键字值的记录调整(排除)出无序区。

iv.重复上述步骤,直到全部记录排好序为止。

*口诀:

先建堆,再找数。

找一次,建一次。

找到数,就输出。(和最后的换位置)

输出完,排序完。*

结论:排序过程中,若采用小根堆,排序后得到的是非递减序列;若采用大根堆,排序后得到的是非递增序列

实现堆排序的2个关键操作:

1.建堆:如何由一个无序序列建成一个堆?

2.堆调整:如何在输出堆顶元素之后,调整剩余元素,使之成为一个新的堆?  

思想(后续示例,均以小根堆为例):

输出堆顶元素之后,以堆中最后一个元素替代之;

然后,将根结点值与左、右子树的根结点值进行比较,并与其中较小者进行交换;

重复上述操作,直到 A)是叶子结点 或 B)其关键字值小于等于左&右子树的关键字的值,即获得新的[小根]堆。

称: 这个从堆顶至叶子的调整过程为“筛选” 。

堆的“筛选”

堆排序算法分析:

堆排序的主要时间花销:初始建堆和重新调整成堆。设记录数为n,所对应的完全二叉树深度为h。

初始建堆:每个非叶子结点都要从上到下做“筛选”。

第 i层结点数≤2i-1,结点下移的最大深度是h-i,而每下移一层要比较2次,则比较次数C1(n)为:

筛选调整:每次筛选要将根结点“下沉”到一个合适位置。

第 i 次筛选时:堆中元素个数为n-i+1;堆的深度是㏒2(n-i+1)+1,则进行n-1次“筛选”的比较次数C2(n)为:

∴ 堆排序时间复杂度T(n)=O(n㏒2n);空间复杂度S(n)=O(1) 。

附加空间: 为元素交换时, 所用的临时空间。

四、归并排序(稳定)

两有序并为一有序

方法:另建表,分别从两表头依次对比。

归并排序

需要注意的是,每次归并后各个区块的长度不一定相等。

归并次数为 l o g 2 n log_2n log2n,时间复杂度 O ( n ) = n l o g 2 n O(n)=nlog_2n O(n)=nlog2n,空间复杂度 n n n

五、基数排序/桶排序/数字排序

与前面四种的不同点:不需要进行关键字的比较和记录的移动。

查找&搜索

概念:

i.查找表(Search Table):相同类型的数据元素(对象)组成的集合,每个元素通常由若干数据项构成。

ii.关键字(Key,码):数据元素中某个(或几个)数据项的值,它可以标识一个数据元素。

若关键字能唯一标识一个数据元素,则关键字称为主关键字;将能标识若干个数据元素的关键字称为次关键字。

iii.查找/检索(Searching):根据给定的Key值,在查找表中确定一个关键字等于给定值的记录或数据元素。

查找表中存在满足条件的记录:查找成功;

查找结果:所查到的记录信息 或记录在查找表中的位置。

查找表中不存在满足条件的记录:查找失败。

查找的基本形式:静态、动态

a.静态查找(Static Search):在查找时只对数据元素进行查询或检索;

实施静态查找的查找表  称为静态查找表。

b.动态查找(Dynamic Search):在实施查找的同时,插入查找表中不存在的记录,或从查找表中删除已存在的某个记录;

实施动态查找的查找表  称为动态查找表。

采用何种查找方法?

根据存储结构的不同,查找方法可分为3大类:

i.顺序表和链表的查找:将给定的K值与查找表中记录的关键字逐个进行比较, 找到要查找的记录;

ii.散列表的查找:根据给定的K值直接访问查找表, 从而找到要查找的记录;

iii.索引查找表的查找:首先根据索引确定待查找记录所在的块 ,然后再从块中找到要查找的记录。

方法的评价指标

查找过程中主要操作是:关键字的比较。

查找过程中关键字的平均比较次数(平均查找长度ASLAverage Search Length)常作为衡量一个查找算法效率高低的标准。

ASL定义为:

Pi:查找第i个记录的概率。不失一般性,认为查找每个记录的概率相等,即P1=P2=…=Pn=1/n;

Ci:查找第i个记录需要进行比较的次数。

1.静态查找

因为线性表是查找表最简单的一种组织方式,因此本节将介绍 4种(主要的)关于顺序存储结构 的查找方法。

a.顺序查找(Sequential Search)

b.折半查找(Binary Search)

c.分块查找

d.Fibonacci查找

1.1顺序查找

思路:

从表的一端开始逐个将记录的关键字和给定K值进行比较,

若某个记录的关键字和给定K值相等,则查找成功;

若扫描完整个表,仍然没有找到相应的记录,则查找失败。

样例:

查找成功 :

查找第n个元素:1 次

……….

查找第 i个元素: n-i+1 次

查找第1个元素: n 次

**查找失败:**n+1 次(查找元素非a1,a2,…,an)

算法实现:


1.2折半查找

思路:

前提条件:查找表中的所有记录是按关键字有序(升序或降序) 。

查找时,

【首先】确定待查找记录在表中的范围,

【然后】逐步缩小范围(每次将待查记录所在区间缩小一半)

直到:找到 或 找不到 记录为止。

示例:

查找成功:

查找不成功:

算法实现:


1.3分块查找

数据组织与查找思想:

1.查找表(不同于普通的数据记录表)的组织

将查找表分成几块。

块间有序,即第i+1块的所有记录关键字均大于(或小于)第i块记录关键字;块内无序。

在查找表的基础上附加一个索引表,

索引表是按关键字有序的,索引表中记录的构成(如图所示);

2.分块查找思想

A.先确定待查记录所在块, B.再在块内’顺序’查找。

算法实现:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值