排序算法

合集下载

排序算法

排序算法

排序算法所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。

排序算法,就是如何使得记录按照要求排列的方法。

排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面。

一个优秀的算法可以节省大量的资源。

在各个领域中考虑到数据的各种限制和规范,要得到一个符合实际的优秀算法,得经过大量的推理和分析。

分类排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个关键字有序的序列。

稳定度(稳定性)一个排序算法是稳定的,就是当有两个相等记录的关键字R和S,且在原本的列表中R出现在S之前,在排序过的列表中R也将会是在S之前。

当相等的元素是无法分辨的,比如像是整数,稳定度并不是一个问题。

然而,假设以下的数对将要以他们的第一个数字来排序。

(4,1)(3,1)(3,7)(5,6)在这个状况下,有可能产生两种不同的结果,一个是依照相等的键值维持相对的次序,而另外一个则没有:(3,1)(3,7)(4,1)(5,6) (维持次序)(3,7)(3,1)(4,1)(5,6) (次序被改变)不稳定排序算法可能会在相等的键值中改变纪录的相对次序,但是稳定排序算法从来不会如此。

不稳定排序算法可以被特别地实现为稳定。

作这件事情的一个方式是人工扩充键值的比较,如此在其他方面相同键值的两个对象间之比较,就会被决定使用在原先数据次序中的条目,当作一个同分决赛。

然而,要记住这种次序通常牵涉到额外的空间负担。

在计算机科学所使用的排序算法通常被分类为:(a)计算的复杂度(最差、平均、和最好性能),依据列表(list)的大小(n)。

一般而言,好的性能是O(nlogn),且坏的性能是O(n^2)。

对于一个排序理想的性能是O(n)。

而仅使用一个抽象关键比较运算的排序算法总平均上总是至少需要O(nlogn)。

(b)存储器使用量(空间复杂度)(以及其他电脑资源的使用)(c)稳定度:稳定的排序算法会依照相等的关键(换言之就是值)维持纪录的相对次序。

十大经典排序算法总结

十大经典排序算法总结

⼗⼤经典排序算法总结最近⼏天在研究算法,将⼏种排序算法整理了⼀下,便于对这些排序算法进⾏⽐较,若有错误的地⽅,还请⼤家指正0、排序算法说明0.1 排序术语稳定:如果a=b,且a原本排在b前⾯,排序之后a仍排在b的前⾯不稳定:如果a=b,且a原本排在b前⾯,排序之后排在b的后⾯时间复杂度:⼀个算法执⾏所耗费的时间空间复杂度:⼀个算法执⾏完所需内存的⼤⼩内排序:所有排序操作都在内存中完成外排序:由于数据太⼤,因此把数据放在磁盘中,⽽排序通过磁盘和内存的数据传输才能进⾏0.2算法时间复杂度、空间复杂度⽐较0.3名词解释n:数据规模k:桶的个数In-place:占⽤常数内存,不占⽤额外内存Out-place:占⽤额外内存0.4算法分类1.冒泡排序冒泡排序是⼀种简单的排序算法。

它重复地⾛访过要排序的数列,⼀次⽐较两个元素,如果它们的顺序错误就把它们交换过来。

⾛访数列的⼯作是重复地进⾏直到没有再需要交换,也就是说该数列已经排序完成。

这个算法的名字由来是因为越⼩的元素会经由交换慢慢“浮”到数列的顶端1.1算法描述⽐较相邻的元素,如果前⼀个⽐后⼀个打,就交换对每⼀对相邻元素做同样的⼯作,从开始第⼀对到结尾最后⼀对,这样在最后的元素应该会是最⼤的数针对所有的元素重复以上的步骤,除了最后⼀个重复步骤1-3,知道排序完成1.2动图演⽰1.3代码实现public static int[] bubbleSort(int[] array) {if (array.length == 0)return array;for (int i = 0; i < array.length; i++)for (int j = 0; j < array.length - 1 - i; j++)if (array[j + 1] < array[j]) {int temp = array[j + 1];array[j + 1] = array[j];array[j] = temp;}return array;}1.4算法分析最佳情况:T(n) = O(n) 最差情况:T(n) = O(n2) 平均情况:T(n) = O(n2)2.选择排序表现简单直观的最稳定的排序算法之⼀,因为⽆论什么数据都是O(n2)的时间复杂度,⾸先在未排序序列中找到最⼩(⼤)元素,与数组中第⼀个元素交换位置,作为排序序列的起始位置,然后再从剩余未排序元素中继续寻找最⼩(⼤)的元素,与数组中的下⼀个元素交换位置,也就是放在已排序序列的末尾2.1算法描述1.初始状态:⽆序区为R[1..n],有序区为空2.第i躺排序开始时,当前有序区和⽆序区R[1..i-1]、R[i..n]3.n-1趟结束,数组有序化2.2动图演⽰2.3代码实现public static int[] selectionSort(int[] array) {if (array.length == 0)return array;for (int i = 0; i < array.length; i++) {int minIndex = i;for (int j = i; j < array.length; j++) {if (array[j] < array[minIndex]) //找到最⼩的数minIndex = j; //将最⼩数的索引保存}int temp = array[minIndex];array[minIndex] = array[i];array[i] = temp;}return array;}2.4算法分析最佳情况:T(n) = O(n2) 最差情况:T(n) = O(n2) 平均情况:T(n) = O(n2)3、插⼊排序是⼀种简单直观的排序算法,通过构建有序序列,对于未排序序列,在已排序序列中从后向前扫描,找到相应位置并插⼊,需要反复把已排序元素逐步向后挪位,为最新元素腾出插⼊空间3.1算法描述1.从第⼀个元素开始,该元素可以认为已经被排序2.取出下⼀个元素(h),在已排序的元素序列中从后往前扫描3.如果当前元素⼤于h,将当前元素移到下⼀位置4.重复步骤3,直到找到已排序的元素⼩于等于h的位置5.将h插⼊到该位置6.重复步骤2-53.2动图演⽰3.3代码实现public static int[] insertionSort(int[] array) {if (array.length == 0)return array;int current;for (int i = 0; i < array.length - 1; i++) {current = array[i + 1];int preIndex = i;while (preIndex >= 0 && current < array[preIndex]) {array[preIndex + 1] = array[preIndex];preIndex--;}array[preIndex + 1] = current;}return array;}3.4算法分析最佳情况:T(n) = O(n) 最坏情况:T(n) = O(n2) 平均情况:T(n) = O(n2)4、希尔排序是简单插⼊排序经过改进之后的⼀个更⾼效的版本,也称为缩⼩增量排序,同时该算法是冲破O(n2)的第⼀批算法之⼀。

计算机常用算法

计算机常用算法

计算机常用算法一、排序算法排序算法是计算机程序中最基本的算法之一,它用于将一组数据按照一定的顺序进行排列。

常见的排序算法包括冒泡排序、选择排序、插入排序、快速排序、归并排序等。

这些算法的目标都是将数据从小到大或从大到小进行排序,以便于后续的处理和查找。

冒泡排序是一种简单的排序算法,它通过不断比较相邻元素的大小来将较大(或较小)的元素逐步交换到右侧(或左侧)。

选择排序则是依次选取未排序部分的最小(或最大)元素并放置到已排序部分的末尾。

插入排序则是将未排序部分的元素依次插入到已排序部分的合适位置。

快速排序是一种高效的排序算法,它通过选择一个基准元素,将数组划分为两个子数组,并对子数组进行递归排序。

归并排序则是将数组分成两个子数组,分别排序后再合并。

二、查找算法查找算法是用于在一组数据中寻找特定元素或满足特定条件的元素的算法。

常见的查找算法包括线性查找、二分查找、哈希查找等。

这些算法的目标都是在最短的时间内找到目标元素。

线性查找是最简单的查找算法,它依次遍历数据中的每个元素,直到找到目标元素或遍历完所有元素。

二分查找则是在有序数组中使用的一种查找算法,它通过不断缩小查找范围,将查找时间从O(n)降低到O(logn)。

哈希查找则是通过构建一个哈希表来实现的,将元素的关键字映射到对应的位置,以实现快速查找。

三、图算法图算法是解决图相关问题的算法,它在计算机科学中有着广泛的应用。

常见的图算法包括深度优先搜索(DFS)、广度优先搜索(BFS)、最短路径算法(Dijkstra算法、Floyd-Warshall算法)、最小生成树算法(Prim算法、Kruskal算法)等。

深度优先搜索是一种遍历图的算法,它从一个起始节点开始,沿着一条路径一直遍历到最后一个节点,然后回溯到前一个节点,继续遍历其他路径。

广度优先搜索则是从起始节点开始,逐层遍历图中的节点,直到找到目标节点。

最短路径算法用于计算图中两个节点之间的最短路径,它可以解决最短路径问题,如求解地图上的最短路径。

所有排序的原理

所有排序的原理

所有排序的原理排序是将一组数据按照某种特定顺序进行排列的过程。

在计算机科学中,排序是一种基本的算法问题,涉及到许多常见的排序算法。

排序算法根据其基本原理和实现方式的不同,可以分为多种类型,如比较排序、非比较排序、稳定排序和非稳定排序等。

下面将详细介绍排序的原理和各种排序算法。

一、比较排序的原理比较排序是指通过比较数据之间的大小关系来确定数据的相对顺序。

所有常见的比较排序算法都基于这种原理,包括冒泡排序、插入排序、选择排序、归并排序、快速排序、堆排序等。

比较排序算法的时间复杂度一般为O(n^2)或O(nlogn),其中n是待排序元素的数量。

1. 冒泡排序原理冒泡排序是一种简单的比较排序算法,其基本思想是从待排序的元素中两两比较相邻元素的大小,并依次将较大的元素往后移,最终将最大的元素冒泡到序列的尾部。

重复这个过程,直到所有元素都有序。

2. 插入排序原理插入排序是一种简单直观的比较排序算法,其基本思想是将待排序序列分成已排序和未排序两部分,初始状态下已排序部分只包含第一个元素。

然后,依次将未排序部分的元素插入到已排序部分的正确位置,直到所有元素都有序。

3. 选择排序原理选择排序是一种简单直观的比较排序算法,其基本思想是每次从待排序的元素中选择最小(或最大)的元素,将其放到已排序部分的末尾。

重复这个过程,直到所有元素都有序。

4. 归并排序原理归并排序是一种典型的分治策略下的比较排序算法,其基本思想是将待排序的元素不断地二分,直到每个子序列只包含一个元素,然后将相邻的子序列两两归并,直到所有元素都有序。

5. 快速排序原理快速排序是一种常用的比较排序算法,其基本思想是通过一趟排序将待排序的元素分割成两部分,其中一部分的元素均比另一部分的元素小。

然后,对这两部分元素分别进行快速排序,最终将整个序列排序完成。

6. 堆排序原理堆排序是一种常用的比较排序算法,其基本思想是利用堆这种数据结构对待排序的元素进行排序。

排序算法十大经典方法

排序算法十大经典方法

排序算法十大经典方法
排序算法是计算机科学中的经典问题之一,它们用于将一组元素按照一定规则排序。

以下是十大经典排序算法:
1. 冒泡排序:比较相邻元素并交换,每一轮将最大的元素移动到最后。

2. 选择排序:每一轮选出未排序部分中最小的元素,并将其放在已排序部分的末尾。

3. 插入排序:将未排序部分的第一个元素插入到已排序部分的合适位置。

4. 希尔排序:改进的插入排序,将数据分组排序,最终合并排序。

5. 归并排序:将序列拆分成子序列,分别排序后合并,递归完成。

6. 快速排序:选定一个基准值,将小于基准值的元素放在左边,大于基准值的元素放在右边,递归排序。

7. 堆排序:将序列构建成一个堆,然后一次将堆顶元素取出并调整堆。

8. 计数排序:统计每个元素出现的次数,再按照元素大小输出。

9. 桶排序:将数据分到一个或多个桶中,对每个桶进行排序,最后输出。

10. 基数排序:按照元素的位数从低到高进行排序,每次排序只考虑一位。

以上是十大经典排序算法,每个算法都有其优缺点和适用场景,选择合适的算法可以提高排序效率。

简单排序算法

简单排序算法

简单排序算法排序算法是计算机科学中最基本、最常用的算法之一。

通过对原始数据集合进行排序,可以更方便地进行搜索、统计、查找等操作。

常用的排序算法有冒泡排序、选择排序、插入排序等。

本文将介绍这些简单排序算法的具体实现及其优缺点。

一、冒泡排序(Bubble Sort)冒泡排序是一种基础的交换排序算法。

它通过不断地交换相邻的元素,从而将数据集合逐渐排序。

具体实现步骤如下:1.比较相邻的元素。

如果第一个比第二个大,就交换它们两个;2.对每一对相邻元素做同样的工作,从第一对到最后一对,这样一轮排序后,就可以确保最后一个元素是最大的元素;3.针对所有元素重复以上的步骤,除了最后一个;4.重复步骤1~3,直到排序完成。

冒泡排序的优点是实现简单、容易理解。

缺点是排序效率较低,尤其是对于较大的数据集合,时间复杂度为O(n²)。

二、选择排序(Selection Sort)选择排序是一种基础的选择排序算法。

它通过在数据集合中选择最小的元素,并将其放置到最前面的位置,然后再从剩余元素中选出最小的元素,放置到已排序部分的末尾。

具体实现步骤如下:1.在未排序序列中找到最小元素,存放到排序序列的起始位置;2.再从剩余未排序元素中继续寻找最小元素,放到排序序列末尾;3.重复步骤1~2,直到排序完成。

选择排序的优点是实现简单、固定时间复杂度O(n²)。

缺点是排序效率仍然较低,尤其是对于大数据集合,因为每次只能交换一个元素,所以相对于冒泡排序,它的移动次数固定。

三、插入排序(Insertion Sort)插入排序是一种基础的插入排序算法。

它将未排序的元素一个一个插入到已排序部分的正确位置。

具体实现步骤如下:1.从第一个元素开始,该元素可以认为已经被排序;2.取出下一个元素,在已经排序的元素序列中从后往前扫描;3.如果该元素(已排序)大于新元素,将该元素移到下一位置;4.重复步骤3,直到找到已排序的元素小于或等于新元素的位置;5.将新元素插入到该位置后;6.重复步骤2~5,直到排序完成。

【十大经典排序算法(动图演示)】 必学十大经典排序算法

【十大经典排序算法(动图演示)】 必学十大经典排序算法

【十大经典排序算法(动图演示)】必学十大经典排序算法0.1 算法分类十种常见排序算法可以分为两大类:比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。

非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。

0.2 算法复杂度0.3 相关概念稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。

不稳定:如果a原本在b的前面,而a=b,排序之后a 可能会出现在b 的后面。

时间复杂度:对排序数据的总的操作次数。

反映当n变化时,操作次数呈现什么规律。

空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。

1、冒泡排序(Bubble Sort)冒泡排序是一种简单的排序算法。

它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。

走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。

这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

1.1 算法描述比较相邻的元素。

如果第一个比第二个大,就交换它们两个;对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;针对所有的元素重复以上的步骤,除了最后一个;重复步骤1~3,直到排序完成。

1.2 动图演示1.3 代码实现1.unction bubbleSort(arr) {2. varlen = arr.length;3. for(vari = 0; i arr[j+1]) {// 相邻元素两两对比6. vartemp = arr[j+1];// 元素交换7. arr[j+1] = arr[j];8. arr[j] = temp;9. }10. }11. }12. returnarr;13.}2、选择排序(Selection Sort)选择排序(Selection-sort)是一种简单直观的排序算法。

8种排序算法

8种排序算法

J=2(38) [38 49] 65 97 76 13 27 49
J=3(65) [38 49 65] 97 76 13 27 49
J=4(97) [38 49 65 97] 76 13 27 49
J=5(76) [38 49 65 76 97] 13 27 49
2. 堆的定义: N个元素的序列K1,K2,K3,...,Kn.称为堆,当且仅当该序列满足特性:
Ki≤K2i Ki ≤K2i+1(1≤ I≤ [N/2])
堆实质上是满足如下性质的完全二叉树:树中任一非叶子结点的关键字均大于等于其孩子结点的关键字。例如序列10,15,56,25,30,70就是一个堆,它对应的完全二叉树如上图所示。这种堆中根结点(称为堆顶)的关键字最小,我们把它称为小根堆。反之,若完全二叉树中任一非叶子结点的关键字均大于等于其孩子的关键字,则称之为大根堆。
(6)基数排序
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序,最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以其是稳定的排序算法。
2. 排序过程:
【示例】:
初始关键字 [49 38 65 97 76 13 27 49]
第一趟排序后 13 [38 65 97 76 49 27 49]
第二趟排序后 13 27 [65 97 76 49 38 49]
第三趟排序后 13 27 38 [97 76 49 65 49]
其次,说一下稳定性的好处。排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。基数排序就是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。另外,如果排序算法稳定,对基于比较的排序算法而言,元素交换的次数可能会少一些(个人感觉,没有证实)。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、冒泡排序
冒泡排序(BubbleSort)的基本概念是:依次比较相邻的两个数,将小数放在前面,大数放在后面。

即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。

然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。

至此第一趟结束,将最大的数放到了最后。

在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。

如此下去,重复以上过程,直至最终完成排序。

代码实现如下:
二、插入排序
插入排序的基本思想是每步将一个待排序的记录按其排序码值的大小,插到前面已经排好的文件中的适当位置,直到全部插入完为止。

插入排序方法主要有直接插入排序和希尔排序。

直接插入排序具体算法描述如下:
1. 从第一个元素开始,该元素可以认为已经被排序
2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5. 将新元素插入到下一位置中
6. 重复步骤2
伪码描述如下:
代码实现如下:
三、归并排序
归并排序是将两个或两个以上的有序子表合并成一个新的有序表。

初始时,把含有n个结点的待排序序列看作由n个长度都为1的有序子表组成,将它们依次两两归并得到长度为2的若干有序子表,再对它们两两合并。

直到得到长度为n的有序表,排序结束。

归并操作的工作原理如下:
1、申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2、设定两个指针,最初位置分别为两个已经排序序列的起始位置
3、比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
4、重复步骤3直到某一指针达到序列尾
5、将另一序列剩下的所有元素直接复制到合并序列尾
代码实现如下:
四、基数排序
设单关键字的每个分量的取值范围均是C0<=Kj<=Crd-1(0<=j<=rd),可能的取值个数rd称为基数.基数的选择和关键字的分解因关键字的类型而异.
(1)若关键字是十进制整数,则按个、十等位进行分解,基数rd=10,C0=0,C9=9,d为最长整数的位数.
(2)若关键字是小写的英文字符串,则rd=26,C0='a',C25='z',d为最长字符串的长度.
基数排序的基本思想是:从低位到高位依次对待排序的关键码进行分配和收集,经过d趟分配和收集,就可以得到一个有序序列.
基数排序从低位到高位进行,使得最后一次计数排序完成后,数组有序。

其原理在于对于待排序的数据,整体权重未知的情况下,先按权重小的因子排序,然后按权重大的因子排序。

例如比较时间,先按日排序,再按月排序,最后按年排序,仅需排序三次。

但是如果先排序高位就没这么简单了。

基数排序源于老式穿孔机,排序器每次只能看到一个列,很多教科书上的基数排序都是对数值排序,数值的大小是已知的,与老式穿孔机不同。

将数值按位拆分再排序,是无聊并自找麻烦的事。

算法的目的是找到最佳解决问题的方案,而不是把简单的事搞的更复杂。

基数排序更适合用于对时间、字符串等这些整体权值未知的数据进行排序。

我的理解是:基数排序算法中,数据可分解为d个因子,每个因子对排序结果都有影响(即权重),先按权重小的因子进行排序,后按权重大的因子进行排序,所有因子排序完即得结果。

如时间可分解为三个因子:日、月、年,先按日对时间排序,再按月对时间排序,最后按年对时间进行排序,即可。

注意:每一趟按因子进行的排序都必须是稳定的!
六、二叉树排序
二叉排序树(Binary Sort Tree)又称二叉查找树。

它或者是一棵空树;或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
我的理解是:二叉树排序,即先建一个二叉排序树,然后中序遍历,即得到一个从小到大的排序结果。

插入结点:
1、首先执行查找算法,找出被插结点的父亲结点。

2、判断被插结点是其父亲结点的左、右儿子。

将被插结点作为叶子结点插入。

3、若二叉树为空。

则首先单独生成根结点。

PS:新插入的结点总是叶子结点。

依次插入数据即完成建树。

伪码实现如下:
删除结点:
将结点z从二叉排序树中删除,分三种情况讨论:
1、如果结点z没有子女,则修改其父结点p[z],使NIL为其子女;
2、如果结点z只有一个子女,则可以通过在其子结点与父结点间建立一条链来删除z;
3、如果结点z只有两个子女,先删除z的后继y(它没有左子女),再用y的内容来替代z的内容。

PS:某一结点x的后继即具有大于key[x]中的关键字中最小者的那个结点,即中序遍历顺序下的后继。

伪码实现如下:
七、选择排序
选择排序的基本思想是每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。

选择排序中主要使用直接选择排序和堆排序。

直接选择排序的过程是:首先在所有记录中选出序码最小的记录,把它与第1个记录交换,然后在其余的记录内选出排序码最小的记录,与第2个记录交换......依次类推,直到所有记录排完为止。

代码实现如下:
八、希尔排序
希尔(Shell)排序的基本思想是:先取一个小于n的整数d1作为第一个增量把文件的全部记录分成d1个组。

所有距离为d1的倍数的记录放在同一个组中。

先在各组内进行直接插入排序;然后,取得第二个增量d2<d1重复上述的分组和排序,直至所取的增量di=1,即所有记录放在同一组中进行直接插入排序为止。

该方法实质上是一种分组插入方法。

一般取d1=n/2,di+1=di/2。

如果结果为偶数,则加1,保证di为奇数。

代码实现如下:
九、堆排序
堆的定义:n个关键字序列Kl,K2,…,Kn称为(Heap),当且仅当该序列满足如下性质(简称为堆性质):
(1) ki≤K2i 且ki≤K2i+1
或(2)Ki≥K2i 且ki≥K2i+1(1≤i≤ n)
若将此序列所存储的向量R[1..n]看作是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。

根结点(堆顶)的关键字是堆里所有结点关键字中最小者,称为小根堆;根结点的关键字是堆里所有结点关键字中最大者,称为大根堆。

用大根堆排序的基本思想如下:
1、先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区
2、再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key
3、由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。

然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。

……
直到无序区只有一个元素为止。

伪码实现如下:
十、快速排序
快速排序采用了一种分治的策略,通常称其为分治法,其基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。

递归地解这些子问题,然后将这些子问题的解组合为原问题的解。

快速排序的具体过程如下:
第一步,在待排序的n个记录中任取一个记录,以该记录的排序码为准,将所有记录分成两组,第1组各记录的排序码都小于等于该排序码,第2组各记录的排序码都大于该排序码,并把该记录排在这两组中间。

第二步,采用同样的方法,对左边的组和右边的组进行排序,直到所有记录都排到相应的位置为止。

代码实现如下:
快速排序的基本思想如下:
1.对数组进行随机化。

2.从数列中取出一个数作为中轴数(pivot)。

3.将比这个数大的数放到它的右边,小于或等于它的数放到它的左边。

4.再对左右区间重复第三步,直到各区间只有一个数。

快速排序的一个重要步骤是对序列进行以中轴数进行划分,左边都小于这个中轴数,右边都大于该中轴数,然后对左右的子序列继续这一步骤直到子序列长度为1
一次划分操作可以分为以下5个步骤:
1.获取中轴元素
2.i从左至右扫描,如果小于基准元素,则i自增,否则记下a[i]
3.j从右至左扫描,如果大于基准元素,则i自减,否则记下a[j]
4.交换a[i]和a[j]
5.重复这一步骤直至i和j交错,然后和基准元素比较,然后交换。

相关文档
最新文档