一、数据结构
2、线性表
顺序表和链表的比较
本章介绍了线性表的逻辑结构及它的两种存储结构:顺序表和链表。这两种表各有短长,在实际应用中应根据问题的要求和性质来选择使用。通过前面的讨论可知:顺序存储有三个优点:
(1) 方法简单,各种高级语言中都有数组,容易实现;
(2) 不用为表示结点间的逻辑关系而增加额外的存储开销;
(3) 具有按元素序号随机访问的特点。
但它也有两大缺点:
(1) 在顺序表中做插入/删除操作时,平均移动大约表中一半的元素,因此当n较大时顺序表的操作效率低。
(2) 需要预先分配足够大的存储空间。若估计过大,容易导致顺序表后部大量闲置;预先分配过小,又会造成溢出。
1.基于空间的考虑
**顺序表的存储空间是静态分配的,在程序执行前必须明确规定它的存储规模。**若线性表长度n变化较大,则存储规模很难预先正确估计。估计太大将造成空间浪费,估计太小又将使空间溢出机会增多。所以当对线性表的长度或存储规模难以估计时,不宜采用顺序存储结构。顺序表的存储密度为1。
**链表不用事先估计存储规模,是动态分配。**只要内存空间尚有空闲,就不会产生溢出。因此,当线性表的长度变化较大,难以估计其存储规模时,以采用动态链表作为存储结构为好。**但链表的存储密度较低。**存储密度是指一个结点中数据元素所占的存储单元和整个结点所占的存储单元之比。显然链式存储结构的存储密度是小于1的。
2.基于时间的考虑
随机存取结构,就是对表中任一结点都可在O(1)时间内直接取得。若对线性表主要做查找,很少做插入和删除操作时,采用顺序存储结构为宜;而在链表中按序号访问的时间性能为O(n)。所以,如果经常做的运算是按序号访问数据元素,显然顺序表优于链表。
而在顺序表中做插入、删除操作时,要平均移动表中一半的元素;尤其是当每个结点的信息量较大时,移动结点的时间开销就相当可观,这一点不应忽视。在链表中的任何位置上进行插入和删除,都只需要修改指针。**对于频繁进行插入和删除的线性表,宜采用链表做存储结构。**若表的插入和删除主要发生在表的首尾两端,则宜采用尾指针表示的单循环链表。
3.基于环境的考虑
顺序表容易实现,任何高级语言中都有数组类型;链表的操作是基于指针的,其使用受语言环境的限制,这也是用户应该考虑的因素之一。
总之,两种存储结构各有特点。选择哪种结构根据实际使用的主要因素决定。通常“较稳定”的线性表选择顺序存储结构;而插/删频繁“动态性“较强的线性表宜选择链式存储结构。
本章小结
本章主要介绍的基本概念是:
**线性表:**一个线性表是n≥0个数据元素a0,a1,a2,…,an-1的有限序列。
**线性表的顺序存储结构:**在计算机中用一组地址连续的存储单元依次存储线性表的各个数据元素,称作线性表的顺序存储结构。
**线性表的链式存储结构:**线性表的链式存储结构就是用一组任意的存储单元——结点(可以是不连续的)存储线性表的数据元素。表中每一个数据元素都由存放数据元素值的数据域和存放直接前驱或直接后继的地址——指针域组成。
**循环链表:**循环链表(Circular Linked List)是将单链表的最后一个结点的指针指向链表的表头结点,使整个链表形成环,从表中任一结点出发都可找到表中其它结点。
**双向链表:**双向链表中的每一个结点除了数据域外,还包含两个指针域:一个指针(next)指向该结点的后继结点,另一个指针(prior)指向它的前驱结点。
3、栈和队列
它们都是对表达式的记法,因此也被称为前缀记法、中缀记法和后缀记法。它们之间的区别在于运算符相对于操作数的位置不同:前缀表达式的运算符位于与其相关的操作数之前;中缀和后缀同理。
举例:
(3 + 4) × 5 - 6 就是中缀表达式
- × + 3 4 5 6 前缀表达式
3 4 + 5 × 6 - 后缀表达式
中缀表达式(中缀记法)
中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。
虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。对计算机来说,计算前缀或后缀表达式的值非常简单。
前缀表达式(前缀记法、波兰式)
前缀表达式的运算符位于操作数之前。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Aq4oW56x-1618591739023)(F:\work_source\books\pic\Snipaste_2021-04-15_02-13-12.png)]
2.一个栈的输入序列为123…n,若输出序列的第一个元素是n,输出第i(1<=i<=n)个元素是()。
A. 不确定 B. n-i+1 C. i D. n-i
3.若已知一个栈的入栈序列是1,2,3,…,n,其输出序列为p1,p2,p3,…,pN,若pN是n,则pi是( )。
A. i B. n-i C. n-i+1 D. 不确定
5.表达式a*(b+c)-d的后缀表达式是( )。
A.abcd* ± *B. abc+ d-
C. abc * +d- D. -+ *abcd
(b+c)*a-d 后缀表达式: bc+a *d-
1、栈
先进后出。进出都是通过栈顶;栈底的元素最后出来
2、队列
先进先出。从队尾进队列,从队头出队列。
4、串
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EHyNtPHl-1618591739045)(F:\work_source\books\pic\image-20210415025706743.png)]
串的模式匹配是一种较复杂的串运算,是模式串在目标串中的定位运算。Brute-Force算法简单易懂,但效率较低。KMP算法对它进行了改进,消除了目标串指针的回溯,提高了算法的效率。
5、数组
数组的性质:
(1) 数组中的数据元素数目固定。一旦定义了一个数组,其数据元素数目不再有增减变化。它属于静态分配存储空间的数据结构。
(2) 数组中的数据元素必须具有相同的数据类型。
(3) 数组中的每个数据元素都有一组唯一的下标值。
(4) 数组是一种随机存储结构。可随机存取数组中的任意数据元素。
存储结构
对于一维数组,数组的存储结构关系为:
LOC(ai)=LOC(a0)+i * k (0≤i<n)
对于二维数组,由于计算机的存储单元是一维线性结构,如何用线性的存储结构存放二维数组元素就有行/列次序问题。常用两种存储方法:以行序(row major order)为主序的存储方式和以列序(column major order)为主序的存储方式。
⑴行优先顺序——将数组元素按行排列,第i+1个行向量紧接在第i个行向量后面。以二维数组为例,按行优先顺序存储的线性序列为:
a11,a12,…,a1n,a21,a22,…a2n,……,am1,am2,…,amn
在PASCAL、C语言中,数组就是按行优先顺序存储的。
⑵列优先顺序——将数组元素按列向量排列,第j+1个列向量紧接在第j个列向量之后,A的m*n个元素按列优先顺序存储的线性序列为:
a11,a21,…,am1,a12,a22,…am2,……,an1,an2,…,anm
在FORTRAN语言中,数组就是按列优先顺序存储的。
【例5-1】对于给定的二维数组float a[3][4],计算:
(1) 数组a中的数组元素数目;
(2) 若数组a的起始地址为1000,且每个数组元素长度为32位(即4个字节),数组元素a[2][3]的内存地址。
【解】(1)由于C语言中数组的行、列下标值的下界均为0,该数组行上界为3-1=2,列上界为4-1=3,所以该数组的元素数目共有3*4=12个。
(2)由于C语言采用行序为主序的存储方式,有:
LOC(a2,3)=LOC(a0,0)+(i*n+j)*k
=1000+(2*4+3)*4
=1044
压缩存储的原则是:不重复存储相同元素;不存储零值元素。
广义表:一种递归表
6、树和二叉树
数据结构:线性结构和非线性结构
线性结构(线性表, 栈,队列等)
非线性结构: 至少存在一个数据元素有不止一个直接前驱或后继(树,图等)
二叉树是另一种树型结构,是度为2的有序树。本章重点讨论了二叉树。二叉树中每个结点至多有两个孩子,它有明确的左、右之分。
一棵深度为h的二叉树,最少含有h个结点,最多含有2h-1个结点;一棵具有n个结点的二叉树,其最小深度为 [log2n]+1。
二叉树具有顺序和链式两种存储结构。对于完全二叉树通常采用顺序存储结构,对于普通二叉树通常采用链式存储结构。
树和二叉树的遍历算法是实现各种操作的基础。是把非线性结构变成线性结构的一种排列方式。对这种非线性结构的遍历需要选择合适的搜索路径,以确保在这条路径上可以访问到结构中的所有数据元素。它包括先序、中序、后序三种不同的遍历次序(树没有中序遍历)。要求读者能熟练掌握二叉树的前序,中序,后序遍历的递归算法,以及树和二叉树之间,森林和树之间转换的具体方法,熟悉线索二叉树的定义及其线索化算法。
作为应用,最后介绍了**最优二叉树**和最优前缀编码的构造方法。最优二叉树是一种“带权路径长度WPL”最短的二叉树,最优前缀编码(哈夫曼编码)是最优二叉树的一种应用。
7、图
**图(Graph)是一种较线性表和树更为复杂的非线性结构。是对结点的前趋和后继个数不加限制的数据结构,用来描述元素之间“多对多”**的关系。
在**线性结构**中,结点之间的关系是线性关系,除开始结点和 终端结点外,每个结点只有一个直接前趋和直接后继。
在**树形结构**中,结点之间的关系实质上是层次关系,同层上的每个结点可以和下一层的零个或多个结点(即孩子)相关,但只能和上一层的一个结点(即双亲)相关(根结点除外)。
在**图结构**中,对结点(图中常称为顶点)的前趋和后继个数不加限制的,即结点之间的关系是任意的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YVil5rLi-1618591739046)(F:\work_source\books\pic\image-20210415231359912.png)]
有向图与无向图
有向图中:边用<x, y>表示,且x与y是有序的。
a. 有向图中的边称为“弧”
b. x——弧尾或初始点 y——弧头或终端点
无向图:边用(x, y) 表示,且顶x与 y是无序的。
完全图
在具有n 个顶点的有向图中,最大弧数为 n(n-1)
在具有n 个顶点的无向图中,最大边数为 n(n-1)/2
顶点的度
无向图:与该顶点相关的边的数目
有向图:
入度ID(v) :以该顶点为头的弧的数目
出度OD(v) :以该顶点为尾头的弧的数目
在有向图中, 顶点的度等于该顶点的入度与出度之和
5.连通性
在无向图中, 若从顶点v1到顶点v2有路径, 则称顶点v1与v2是连通的。如果图中任意一对顶点vi和vj(vi,vj∈V)都是连通的, 则称此图是连通图。**非连通图的极大连通子图叫做连通分量。**
6 .强连通图与强连通分量
在有向图中, 若对于每一对顶点vi和vj, 都存在一条从vi到vj和从vj到vi的路径, 则称此图是强连通图。
非强连通图的极大强连通子图叫做强连通分量。
7.网络
权 某些图的边或弧具有与它相关的数, 称之为权。权可以代表一个顶点到另一个顶点的距离,耗费等。
网络 这种带权连通图一般称为网络。
8.生成树、生成森林
生成树 一个连通图的生成树是它的极小连通子图,在n个顶点的情形下,有n-1条边。
生成树是对连通图而言的
是连同图的极小连同子图
包含图中的所有顶点
有且仅有n-1条边
非连通图的生成树则组成一个生成森林。若图中有n个顶点,m个连通分量,则生成森林中有n-m条边。
顶点表: 一个记录各个顶点信息的一维数组,
**邻接矩阵:**一个表示各个顶点之间的关系(边或弧)的二维数组。
在有向图的邻接表中,第 i 个链表中结点的个数是顶点Vi的出度。[出边表]
在有向图的逆邻接表中,第 i 个链表中结点的个数是顶点Vi 的入度。[入边表]
最小生成树
依次选权重最小边,相邻且无回路
最短路径
已选入S,求与已选点的路径的min的路线,点入S
8、查找
查找表是记录的集合,每个记录至少包含一个关键字。所谓查找就是根据给定的关键字值,在查找表中找出一个记录,该记录的关键字值等于给定的值。
若在查找的同时对表做修改运算(如插入和删除),则相应的表称之为**动态查找表**,否则称之为**静态查找表**。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H8as5FsG-1618591739048)(F:\work_source\books\pic\image-20210416230155301.png)]
平均查找长度ASL定义为:
n 是查找表中记录的个数
Pi 是查找第i个记录的概率
Ci 是找到第i个记录所需进行的比较次数。
8.2 静态查找表
8.2.1 简单顺序查找
在等概率情况下pi=1/n;Ci=i
ASL=(n+1)/2
顺序查找算法的时间复杂性为O(n)。
8.2.2 二分/折半查找
**二分查找的基本思想是:**首先确定待查记录所在的范围(区域)。假设用变量low和high分别表示当前查找区域的首尾下标。将待查关键字k和该区域的中间元素,其下标为mid=(low+high)/2的关键字进行比较。比较的结果有如下三种情况:
(1)k==A[mid].key:查找成功,返回mid的值。
(2)k<A[mid].key:则由表的有序性可知,若表中存在关键字等于k的记录,则该记录必定是在位置mid左边的区域(下标从low到mid-1)中。因此应在此区域继续取中间位置记录的关键字进行比较。
(3)k>A[mid].key:说明元素只可能在右边区域(下标从mid+1到high)。因此应在此区域继续取中间位置记录的关键字进行比较。
在查找概率相同的情况下,Pi=1/n。查找成功的平均查找长度为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cPwDKPJC-1618591739049)(F:\work_source\books\pic\image-20210416230930988.png)]
二分查找算法比顺序查找算法平均查找长度为 n/2的比较次数少,查找速度快。虽然二分查找的效率高,但是要将表按关键字排序。
8.2.3 分块查找
基本思想是:首先把表长为n的线性表分成b块,前b-1块记录个数为s=n/b,第b块的记录个数小于等于s。在每一块中,结点的存放不一定有序,但块与块之间必须是分块有序的(假定按结点的关键字值递增有序)。即指后一个块中所有记录的关键字值都应比前一个块中所有记录的关键字值大。为实现分块检索,还需建立一个索引表。索引表的每个元素对应一个块,其中包括该块内最大关键字值和块中第一个记录位置的地址指针。显然这个索引顺序表是一个递增有序表。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g4lS9YWT-1618591739050)(F:\work_source\books\pic\image-20210416231634528.png)]
在这种结构下,查找过程要分为两步:首先查找索引表。因为索引表是有序表,所以可采用二分查找或顺序查找,以确定给定值所在的块。因为块中的记录可以是任意排列的,所以再在已确定的块中进行顺序查找。
b个块,每个块的长度s=n/b
8.3 树表的动态查找
8.3.1 二叉排序树
二叉排序树又称为二叉查找树。它或者是空树,或者是满足如下性质的二叉树:
(1)若它的左子树非空,则左子树上所有结点的值均小于根结点的值。
(2)若它的右子树非空,则右子树上所有结点的值均大于根结点的值。
(3)它的左、右子树本身又各是一棵二叉排序树。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-meSWJkxi-1618591739050)(F:\work_source\books\pic\image-20210416233228857.png)]
插入的基本思想是:
若二叉排序树为空,将待插入的结点作为根结点。否则,若待插入结点的关键字值和根结点关键字值进行比较。若小于,则作为根结点左子树插入,否则作为右子树插入。其非递归算法描述为:
查找的基本思想:
(1)当二叉树为空树时,检索失败。
(2)如果二叉排序树根结点的关键字等于待检索的关键字,则检索成功。
(3)如果二叉排序树根结点的关键字小于待检索的关键字,则在根结点的右子树中用相同的方法继续检索。
(4)如果二叉排序树根结点的关键字大于待检索的关键字,则在根结点的左子树中用相同的方法继续检索。
删除的基本思想:
(1)若待删除的结点是叶结点,直接删去该结点。
(2)若待删除的结点只有左子树而无右子树。根据二叉排序树的特点,可以直接将其左子树的根结点放在被删结点的位置。
(3)若待删除的结点只有右子树而无左子树。与(2)情况类似,可以直接将其右子树的根结点放在被删结点的位置。
(4)若待删除的结点同时有左子树和右子树。根据二叉排序树的特点,可以从其左子树中选择关键字最大的结点或右子树中选择关键字最小的结点放在被删去结点的位置上。假如选取右子树上关键字最小的结点,那么该结点一定是右子树的最左结点。
8.3.2 平衡二叉树
(1)平衡二叉树的左右子树都是平衡二叉树
(2)各个结点左子树和右子树的深度之差的绝对值不超过1
8.3.3 B-树
B-树又称为多路平衡查找树。
B-树中所有结点的孩子结点最大值称为B-树的阶,通常用m表示。从查找效率考虑,一般要求m≥3。一棵m阶的B-树或者是一棵空树,或者是满足下列要求的m叉树:
(1)根结点或者为叶子,或者至少有两棵子树,至多有m棵子树。
(2)除根结点外,所有非终端结点至少有棵子树,至多有m棵子树。
(3)所有叶子结点都在树的同一层上。
(4)每个结点的结构为:
(n,A0,K1,A1,K2,A2,… ,Kn,An)
其中,Ki(1≤i≤n)为关键字,Ki<Ki+1(1≤i≤n-1)
Ai(0≤i≤n)为指向子树根结点的指针。且Ai所指子树所有结点中的关键字均小于Ki+1。An所指子树中所有结点的关键字均大于Kn。
n为结点中关键字的个数,满足1≤n≤m-1。
n:关键字个数
m:树的阶数 [m/2]≤n≤m-1
插入的过程分两步完成:
(1)利用前述的B-树的查找算法查找关键字的插入位置。若找到,则说明该关键字已经存在,直接返回。否则查找操作必失败于某个最低层的非终端结点上。
(2)判断该结点是否还有空位置。即判断该结点的关键字总数是否满足n<m-1。若满足,则说明该结点还有空位置,直接把关键字k插入到该结点的合适位置上。若不满足,说明该结点己没有空位置,需要把结点分裂成两个。
**分裂的方法是:**生成一新结点。把原结点上的关键字和k按升序排序后,从中间位置(即之处)把关键字(不包括中间位置的关键字)分成两部分。左部分所含关键字放在旧结点中,右部分所含关键字放在新结点中,中间位置的关键字连同新结点的存储位置插入到父结点中。如果父结点的关键字个数也超过(m-1),则要再分裂,再往上插。直至这个过程传到根结点为止。
在B-树上删除关键字k的过程分两步完成:
(1)利用前述的B-树的查找算法找出该关键字所在的结点。然后根据 k所在结点是否为叶子结点有不同的处理方法。
(2)若该结点为非叶结点,且被删关键字为该结点中第i个关键字key[i],则可从指针son[i]所指的子树中找出最小关键字Y。代替key[i]的位置,然后在叶结点中删去Y。
因此,把在非叶结点删除关键字k的问题就变成了删除叶子结点中的关键字的问题了。
在B-树叶结点上删除一个关键字的方法是
首先将要删除的关键字 k直接从该叶子结点中删除。然后根据不同情况分别作相应的处理,共有三种可能情况:
(1)如果被删关键字所在结点的原关键字个数n> m/2,说明删去该关键字后该结点仍满足B-树的定义。这种情况最为简单,只需从该结点中直接删去关键字即可。
(2)如果被删关键字所在结点的关键字个数n==m/2,说明删去该关键字后该结点将不满足B-树的定义,需要调整。
调整过程为:如果其左右兄弟结点中有“多余”的关键字。则可将右(左)兄弟结点中最小(大)关键字上移至双亲结点。而将双亲结点中小(大)于该上移关键字的关键字下移至被删关键字所在结点中。
(3)如果左右兄弟结点中没有“多余”的关键字,这种情况比较复杂。需把要删除关键字的结点与其左(或右)兄弟结点以及双亲结点中分割二者的关键字合并成一个结点。如果因此使双亲结点中关键字个数小于m/2,则对此双亲结点做同样处理。以致于可能直到对根结点做这样的处理而使整个树减少一层。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M9p3bHhZ-1618591739051)(F:\work_source\books\pic\image-20210417002213015.png)]
8.4 哈希表查找
8.4.2 构造哈希函数
1、直接定址法
H(k)=k+c (c≥0)
这种哈希函数计算简单,并且不可能有冲突发生。当关键字的分布基本连续时,可使用直接定址法的哈希函数。否则,若关键字分布不连续将造成内存单元的大量浪费。
2.除留余数法
取关键字k除以哈希表长度m所得余数作为哈希函数地址的方法。即:
H(k)=k%m
这是一种较简单、也是较常见的构造方法。这种方法的关键是选择好哈希表的长度m。使得数据集合中的每一个关键字通过该函数转化后映射到哈希表的任意地址上的概率相等。理论研究表明,在m取值为素数(质数)时,冲突可能性相对较少。
3.平方取中法
取关键字平方后的中间几位作为哈希函数地址(若超出范围时,可再取模)。
4.折叠法
这种方法适合在关键字的位数较多,而地址区间较小的情况。
将关键字分隔成位数相同的几部分。然后将这几部分的叠加和作为哈希地址(若超出范围,可再取模)。
例如,假设关键字为某人身份证号码430104681015355,则可以用4位为一组进行叠加。即有5355+8101+1046+430=14932,舍去高位。
则有H(430104681015355)=4932
为该身份证关键字的哈希函数地址。
5. 数值分析法
8.4.3 冲突的解决办法
同一个地址上面存在多个数
解决方法**:开发地址法、链地址法**
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X3yYREvh-1618591739052)(F:\work_source\books\pic\image-20210417004026543.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fQvfhXcW-1618591739052)(F:\work_source\books\pic\image-20210417004118269.png)]
(2)平方探查法
设发生冲突的地址为d,则平方探查法的探查序列为:d+12,d+22,…直到找到一个空闲位置为止。
平方探查法的数学描述公式为:
d0=H(k)
di=(d0+i2) % m (1≤i≤m-1)
2、链地址法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EYt7r8f8-1618591739053)(F:\work_source\books\pic\image-20210417004415045.png)]
由于在各链表中的第一个元素的查找长度为l,第二个元素的查找长度为2,依此类推。因此,在等概率情况下成功的平均查找长度为:
(1*5+2*2+3*l+4*1)/9=16/9
9、排序
9.2 插入排序
9.2.1 直接插入排序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HowwNjgG-1618591739054)(F:\work_source\books\pic\image-20210416001207337.png)]
9.2.2 折半插入排序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N7yx0dvy-1618591739054)(F:\work_source\books\pic\image-20210416001711381.png)]
插入e, num[i] i从1开始
初始low=1 high=7
mid=int((low+high)/2)
(1)、e<num[mid]
high = mid-1
重新计算mid
(2)、e>num[mid]
low = mid+1
(3)当high<low时,插入位置便是low
9.2.3 希尔排序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gpwf3gkE-1618591739055)(F:\work_source\books\pic\image-20210416002252165.png)]
第一趟排序时,取d1=5,整个序列被划分成5组,分别为{58,25},{46,37},{72,58},{95,63},{84,12}。对各组内的记录进行直接插入排序,得到第一趟排序结果如图8-3(a)所示。
第二趟排序时,取d2=3,将第一趟排序的结果分成3组,分别为{25,63,46,84},{37,12,72},{58,58,95}。再对各组内记录进行直接插入排序,得到第二趟排序结果如图8-3(b)所示。25 12 58 46 37 58 63 72 95 84
第三趟排序时,取d3=1,所有的数据记录分成1组{25 ,12,58 ,46,37,58 ,63, 72, 95,84},此时序列基本“有序”,对其进行直接插入排序,最后得到希尔排序的结果如图8-3(c )所示。
12 25 37 46 58 58 63 72 86 95。
9.3 快速排序
见自己博客
9.4 选择排序
选择排序(Selection Sort)的基本思想是:不断从待排记录序列中选出关键字最小的记录插入已排序记录序列的后面,直到n个记录全部插入已排序记录序列中。本节主要介绍两种选择排序方法:简单选择排序和堆排序。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bs0a1Jvv-1618591739056)(F:\work_source\books\pic\image-20210416002820152.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0n0AxhcI-1618591739057)(F:\work_source\books\pic\image-20210416003450732.png)]
(1) 若n较小(如n值小于50),对排序稳定性不作要求时,宜采用选择排序方法,若关键字的值不接近逆序,亦可采用直接插入排序法。但如果规模相同,且记录本身所包含的信息域比较多的情况下应首选简单选择排序方法。因为直接插入排序方法中记录位置的移动操作次数比直接选择排序多,所以选用直接选择排序为宜。
(2) 如果序列的初始状态已经是一个按关键字基本有序的序列,则选择直接插入排序方法和冒泡排序方法比较合适,因为“基本”有序的序列在排序时进行记录位置的移动次数比较少。
2,58 ,46,37,58 ,63, 72, 95,84},此时序列基本“有序”,对其进行直接插入排序,最后得到希尔排序的结果如图8-3(c )所示。
12 25 37 46 58 58 63 72 86 95。
9.3 快速排序
见自己博客
9.4 选择排序
选择排序(Selection Sort)的基本思想是:不断从待排记录序列中选出关键字最小的记录插入已排序记录序列的后面,直到n个记录全部插入已排序记录序列中。本节主要介绍两种选择排序方法:简单选择排序和堆排序。
[外链图片转存中…(img-bs0a1Jvv-1618591739056)]
[外链图片转存中…(img-0n0AxhcI-1618591739057)]
(1) 若n较小(如n值小于50),对排序稳定性不作要求时,宜采用选择排序方法,若关键字的值不接近逆序,亦可采用直接插入排序法。但如果规模相同,且记录本身所包含的信息域比较多的情况下应首选简单选择排序方法。因为直接插入排序方法中记录位置的移动操作次数比直接选择排序多,所以选用直接选择排序为宜。
(2) 如果序列的初始状态已经是一个按关键字基本有序的序列,则选择直接插入排序方法和冒泡排序方法比较合适,因为“基本”有序的序列在排序时进行记录位置的移动次数比较少。
(3) 如果n较大,则应采用时间复杂度为O(nlog2n)的排序方法,**即快速排序、堆排序或归并排序方法。**快速排序是目前公认的内部排序的最好方法,当待排序的关键字是随机分布时,快速排序所需的平均时间最少;堆排序所需的时间与快速排序相同,但辅助空间少于快速排序,并且不会出现最坏情况下时间复杂性达到O(n2)的状况。这两种排序方法都是不稳定的,**若要求排序稳定则可选用归并排序。**通常可以将它和直接插入排序结合在一起用。先利用直接插入排序求得两个子文件,然后,再进行两两归并。