《信息学奥赛——排序算法》由会员分享,可在线阅读,更多相关《信息学奥赛——排序算法(8页珍藏版)》请在金锄头文库上搜索。
1、全国青少年信息学奥林匹克联赛全国青少年信息学奥林匹克联赛排序算法排序算法一、插入排序一、插入排序(Insertion Sort)1. 基本思想:每次将一个待排序的数据元素,插入到前面已经排好序的数列中的适当位置,使数列依然有序;直到待排序数据元素全部插入完为止。2. 排序过程: 【示例】:初始关键字 49 38 65 97 76 13 27 49J=2(38) 38 49 65 97 76 13 27 49J=3(65) 38 49 65 97 76 13 27 49J=4(97) 38 49 65 97 76 13 27 49J=5(76) 38 49 65 76 97 13 27 49J=
2、6(13) 13 38 49 65 76 97 27 49J=7(27) 13 27 38 49 65 76 97 49J=8(49) 13 27 38 49 49 65 76 97 Procedure InsertSort(Var R : FileType);/对 R1.N按递增序进行插入排序, R0是监视哨/Beginfor I := 2 To N Do /依次插入 R2,.,Rn/beginR0 := RI; J := I - 1;While R0 I Then /交换 RI和 RK /begin Temp := RI; RI := RK; RK := Temp; end;endEnd.
3、 /SelectSort /三、冒泡排序三、冒泡排序(BubbleSort)1. 基本思想:两两比较待排序数据元素的大小,发现两个数据元素的次序相反时即进行交换,直到没有反序的数据元素为止。2. 排序过程:设想被排序的数组 R1.N垂直竖立,将每个数据元素看作有重量的气泡,根据轻气泡不能在重气泡之下的原则,从下往上扫描数组 R,凡扫描到违反本原则的轻气泡,就使其向上“漂浮“,如此反复进行,直至最后任何两个气泡都是轻者在上,重者在下为止。【示例】:49 13 13 13 13 13 13 13 38 49 27 27 27 27 27 2765 38 49 38 38 38 38 3897 65
4、 38 49 49 49 49 4976 97 65 49 49 49 49 4913 76 97 65 65 65 65 6527 27 76 97 76 76 76 7649 49 49 76 97 97 97 97 Procedure BubbleSort(Var R : FileType) /从下往上扫描的起泡排序/BeginFor I := 1 To N-1 Do /做 N-1 趟排序/beginNoSwap := True; /置未排序的标志/For J := N - 1 DownTo 1 Do /从底部往上扫描/beginIf RJ+1= X) And (I X /begin R
5、J := RI; /相当于交换 RI和 RJ/J := J - 1endUntil I = J;RI := X /基准 X 已被最终定位/End; /Parttion /Procedure QuickSort(Var R :FileType; S,T: Integer); /对 RS.T快速排序/BeginIf S T Then /当 RS.T为空或只有一个元素是无需排序/beginPartion(R, S, T, I); /对 RS.T做划分/QuickSort(R, S, I-1); /递归处理左区间 RS,I-1/QuickSort(R, I+1,T); /递归处理右区间 RI+1.T
6、/end;End. /QuickSort/五、堆排序五、堆排序(Heap Sort)1. 基本思想:堆排序是一树形选择排序,在排序过程中,将 R1.N看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。2. 堆的定义: N 个元素的序列 K1,K2,K3,.,Kn.称为堆,当且仅当该序列满足特性:KiK2i Ki K2i+1(1 I N/2)堆实质上是满足如下性质的完全二叉树:树中任一非叶子结点的关键字均大于等于其孩子结点的关键字。例如序列 10,15,56,25,30,70 就是一个堆,它对应的完全二叉树如上图所示。这种堆中根结点(称为堆顶)
7、的关键字最小,我们把它称为小根堆。反之,若完全二叉树中任一非叶子结点的关键字均大于等于其孩子的关键字,则称之为大根堆。3. 排序过程:堆排序正是利用小根堆(或大根堆)来选取当前无序区中关键字小(或最大)的记录实现排序的。我们不妨利用大根堆来排序。每一趟排序的基本操作是:将当前无序区调整为一个大根堆,选取关键字最大的堆顶记录,将它和无序区中的最后一个记录交换。这样,正好和直接选择排序相反,有序区是在原记录区的尾部形成并逐步向前扩大到整个记录区。【示例】:对关键字序列 42,13,91,23,24,16,05,88 建堆 Procedure Sift(Var R :FileType; I, M :
8、 Integer);/在数组 RI.M中调用 RI,使得以它为完全二叉树构成堆。事先已知其左、右子树(2I+1 =M 时)均是堆/BeginX := RI; J := 2*I; /若 J =M, RJ是 RI的左孩子/While J = M Do /若当前被调整结点 RI有左孩子 RJ/beginIf (J M) And RJ.Key RJ+1.Key ThenJ := J + 1 /令 J 指向关键字较大的右孩子/J 指向 RI的左、右孩子中关键字较大者/If X.Key RJ.Key Then /孩子结点关键字较大/beginRI := RJ; /将 RJ换到双亲位置上/I := J ;
9、J := 2*I /继续以 RJ为当前被调整结点往下层调整/end;ElseExit /调整完毕,退出循环/endRI := X; /将最初被调整的结点放入正确位置/End;/Sift/Procedure HeapSort(Var R : FileType); /对 R1.N进行堆排序/BeginFor I := N Div Downto 1 Do /建立初始堆/Sift(R, I , N)For I := N Downto 2 do /进行 N-1 趟排序/beginT := R1; R1 := RI; RI := T; /将当前堆顶记录和堆中最后一个记录交换/Sift(R, 1, I-1)
10、 /将 R1.I-1重成堆/endEnd; /HeapSort/六、几种排序算法的比较和选择六、几种排序算法的比较和选择 1. 选取排序方法需要考虑的因素:(1) 待排序的元素数目 n;(2) 元素本身信息量的大小;(3) 关键字的结构及其分布情况;(4) 语言工具的条件,辅助空间的大小等。2.2. 小结:小结:(1) 若 n 较小(n = 50),则可以采用直接插入排序或直接选择排序。由于直接插入排序所需的记录移动操作较直接选择排序多,因而当记录本身信息量较大时,用直接选择排序较好。(2) 若文件的初始状态已按关键字基本有序,则选用直接插入或冒泡排序为宜。(3) 若 n 较大,则应采用时间复杂度为 O(nlog2n)的排序方法:快速排序、堆排序或归并排序。 快速排序是目前基于比较的内部排序法中被认为是最好的方法。(4) 在基于比较排序方法中,每次比较两个关键字的大小之后,仅仅出现两种可能的转移,因此可以用一棵二叉树来描述比较判定过程,由此可以证明:当文件的 n个关键字随机分布时,任何借助于“比较“的排序算法,至少需要 O(nlog2n)的时间。(5) 当记录本身信息量较大时,为避免耗费大量时间移动记录,可以用链表作为存储结构。