排序算法稳定性

内部排序方法

喜夏-厌秋 提交于 2019-12-06 22:02:43
1、分类 按平均时间将排序分为四类: a、平方阶(O(n2))排序 一般称为简单排序,例如直接插入、直接选择和冒泡排序; b、线性对数阶(O(nlgn))排序 如快速、堆和归并排序; c、O(n1+£)阶排序  £是介于0和1之间的常数,即0<£<1,如希尔排序; d、线性阶(O(n))排序 如桶、箱和基数排序。 2、各种排序方法比较 简单排序中直接插入最好,快速排序最快,当文件为正序时,直接插入和冒泡均最佳。 3、影响排序效果的因素 因为不同的排序方法适应不同的应用环境和要求,所以选择合适的排序方法应综合考虑下列因素: ① 待排序的记录数目n; ② 记录的大小(规模); ③ 关键字的结构及其初始状态; ④ 对稳定性的要求; ⑤ 语言工具的条件; ⑥ 存储结构; ⑦ 时间和辅助空间复杂度等。 4、排序方法的选择 (1)、若n较小(如n≤50),可采用直接插入或直接选择排序。 当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插人,应选直接选择排序为宜。 (2)、若文件初始状态基本有序(指正序),则应选用直接插人、冒泡或随机的快速排序为宜。 (3)、若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序或归并排序。 快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;

数据结构之内外排序

喜你入骨 提交于 2019-12-06 06:59:06
一、内排序 排序类别 排序方法 最好时间复杂度 平均时间复杂度 最坏时间复杂度 辅助空间 稳定性 备注 插入类 插入 O(n) O(n 2 ) O(n 2 ) O(1) 稳定 大部分已排序时较好 希尔排序 - O(n s ),1<s<2 - O(1) 不稳定 s是所选分组 交换类 冒泡排序 O(n) O(n 2 ) O(n 2 ) O(1) 稳定 n小时较好 快速排序 O(nlogn) O(nlogn) O(n 2 ) O(logn) 不稳定 n大时较好 选择类 选择 O(n 2 ) O(n 2 ) O(n 2 ) O(1) 不稳定 n小时较好 堆排序 O(nlogn) O(nlogn) O(nlogn) O(1) 不稳定 n大时较好 归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) 稳定 n大时较好 基数排序 O(d(n+rd)) O(d(n+rd)) O(d(n+rd)) O(rd) 稳定 见下文 1.插入排序(InsertSort) 插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的

几种常见排序方法的基本介绍,性能分析,和c语言实现

不羁的心 提交于 2019-12-06 00:50:17
本文介绍8种常见的排序算法,以及他们的原理,性能分析和c语言实现: 为了能够条理清楚, 本文所有的算法和解释全部按照升序排序进行 首先准备一个元素无序的数组arr[],数组的长度为length,一个交换函数swap, 在main函数中实现排序函数的调用,并输出排序结果: void swap(int*x , int*y) { int temp = *x; *x = *y; *y = temp; } int main() { int arr[] = { 1,8,5,7,4,6,2,3}; int length = sizeof(arr) / sizeof(int); sort(arr, length); for (int i = 0;i < length;i++) { printf("%d\n", arr[i]); } return 0; } 插入排序 第一次循环: 第二次循环: 第三次循环: 外层循环每执行一次就从无序区向有序区中插入一个数据arr[i]   里层循环控制插入的数据arr[i]与其前一个数据比较,如果比前一个数据小,就让前一个数据后移1位   ...不断重复上述步骤,直到找到不比arr[i]小的数据arr[j],因为arr[j]后面的数据都后移了1位,所以直接将arr[i]放在空闲的arr[j+1]位置 c程序实现: void CRsort(int arr[],

经典排序算法

随声附和 提交于 2019-12-05 08:34:10
  排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。用一张图概括: 关于时间复杂度: 平方阶 (O(n2)) 排序 各类简单排序:直接插入、直接选择和冒泡排序。 线性对数阶 (O(nlog2n)) 排序 快速排序、堆排序和归并排序。 O(n1+§)) 排序,§ 是介于 0 和 1 之间的常数。 希尔排序。 线性阶 (O(n)) 排序 基数排序,此外还有桶、箱排序。 关于稳定性: 稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序。 不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序。 名词解释: n:数据规模 k:“桶”的个数 In-place:占用常数内存,不占用额外内存 Out-place:占用额外内存 稳定性:排序后 2 个相等键值的顺序和排序之前它们的顺序相同 冒泡排序   冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

算法 - 排序算法的稳定性

蹲街弑〆低调 提交于 2019-12-05 02:03:46
排序算法的稳定性 排序的稳定性,指原有数据相同值的原始次序不变。 可以: 冒泡排序遇到相等的数不交换即可做到稳定。 插入排序,遇到相等的数即停止比较,插入数组。 归并排序 merge 过程中,遇到相等的值先填入左区域的值就可以做到稳定。 不可以: 选择排序不能做到稳定性,选择数值的时候交换数字是会打乱原始的次序。 随机快排不具有稳定性,因此荷兰国旗问题也是不能做到稳定性的。 堆排序。 稳定性的意义: 现实工程中需要 保持上一次排序时遗留的信息 ,比如学校的成绩排序,第一次查询以成绩高低排序,第二次查询以班级排序,如果排序算法具有稳定性,就可以保留上一次查询的信息,那么第二次查询得到的结果就是以班级和成绩高低两项指标排序的成绩。 排序总结 工程上的排序算法是综合排序:先调用快排或归并排序,再调用插入排序。 在样本量小于 60 的时候使用插入排序,对比冒泡排序和选择排序,插入排序的时间复杂度是受数据状况影响的,范围是 [O(n), O(n^2)] , 而且其代码简洁,常数项低; 样本量大于 60 的时候,在能使用快排的场景下,如不用区分数据的差异,不追求稳定性,这时选用快排,因为其非常简洁,操作少,常数项低;需要区分数据的差异,要求算法具有稳定性的时候使用归并排序。 工程中需要将快排和归并排序的递归调用部分改写成非递归的调用。 归并排序空间复杂度是 O(N),可以变成 O(1)

数据结构与算法之美学习笔记:第十三讲

大城市里の小女人 提交于 2019-12-05 00:24:45
一、课前问题 上两节中,我带你着重分析了几种常用排序算法的原理、时间复杂度、空间复杂度、稳定性等。今天,我会讲三种时间复杂度是O(n)的排序算法:桶排序、计数排序、基数排序。 因为这些排序算法的时间复杂度是线性的,所以我们把这类排序算法叫作线性排序(Linear sort)。之所以能做到线性的时间复杂度,主要原因是,这三个算法是非基于比较的排序算法, 都不涉及元素之间的比较操作。 这几种排序算法理解起来都不难,时间、空间复杂度分析起来也很简单,但是对要排序的数据要求很苛刻,所以我们今天 学习重点的是掌握这些排序算法的适用场景 。 按照惯例,我先给你出一道思考题: 如何根据年龄给100万用户排序? 你可能会说,我用上一节课讲的归并、快排就可以搞定啊!是的,它们也可以完成功能,但是时间复杂度最低也是O(nlogn)。有没有更快的排序方法呢?让我们一起进入今天的内容! 二、桶排序(Bucket sort) 1、桶排序的核心思想 首先,我们来看桶排序。桶排序,顾名思义,会用到“桶”,核心思想是将要排序的数据分到一个有序的桶里,每个桶里的数据 再单独进行排序。桶内排完序之后,再把每个桶里的数据按照顺序依次取出,组成的序列就是有序的了。 桶排序的时间复杂度为什么是O(n)呢?我们一块儿来分析一下。 如果要排序的数据有n个,我们把它们均匀地划分到m个桶内,每个桶里就有k=n/m个元素。

选择排序算法:堆排序-Heap Sort

陌路散爱 提交于 2019-12-04 22:28:50
基本思想 排序思想 用最大堆排序的基本思想: 先将初始文件R[1..n]建成一个最大堆,此堆为初始的无序堆。 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得 到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key。 由于交换后新的根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]调整为堆。 算法实现 最大堆排序算法,Java实现,代码如下所示: public abstract class Sorter { public abstract void sort ( int [] array); } public class HeapSorter extends Sorter { public void sort ( int [] array) { heapSort(array); } private void heapSort ( int [] array) { int temp; // 用于交换的暂存单元

排序算法---之插入排序(直接插入排序&希尔排序)

别来无恙 提交于 2019-12-04 19:08:04
排序算法--之插入排序 一、排序算法分为: 1.插入排序(直接插入排序&希尔排序) 2.交换排序(冒泡排序&快速排序) 3.选择排序(直接选择排序&堆排序) 4.归并排序 二、下面这张图对排序算法的时间复杂度&空间复杂度&稳定性做了一个总结: 二(1)、插入排序-----直接插入排序 1.算法代码(升序) //直接插入排序 void InsertSort(int *a,size_t n) { assert(a); for(size_t i=0;i<n-1;++i) { int end = i;//下标 int tmp = a[end+1];//要插入的那个数 while(end>=0) { if(a[end]>tmp) { a[end+1] = a[end]; --end; } else { break; } } a[end+1] = tmp;//若最小的数在最后一个,end会--到-1, } } //测试代码 void PrintArray(int* a,size_t n) { for(size_t i=0;i<n;++i) { cout<<a[i]<<" "; } cout<<endl; } //测试代码 void InsertSortTest() { int a[]={2,5,4,0,9,3,6,8,7,1}; PrintArray(a,sizeof(a)/sizeof(a

排序算法分析1--冒泡排序、插入排序、选择排序

邮差的信 提交于 2019-12-04 19:07:31
排序算法分析1--冒泡排序、插入排序、选择排序 0.综述 1.冒泡排序(Bubble sort) 1.1冒泡排序算法原理 1.2冒泡排序算法优化与代码实现 1.3冒泡排序算法分析 2.插入排序(Insertion sort) 2.1插入排序算法原理 2.2直接插入排序代码实现 2.3直接插入排序算法分析 2.4折半插入排序算法 3.选择排序(Slection sort) 3.1选择排序算法原理 3.2选择排序代码实现 3.3选择排序算法分析 0.综述 所谓排序,就是将原本无序的序列重新排列成有序序列的过程 。排序算法对任何一个程序员来说都是一项基本功,在实际的项目中我们也经常需要使用排序。排序算法的选择和使用不仅要针对实际数据的特点,有时候排序的稳定性也必须考虑。这样可以提高程序的运行效率,让开发工作事半功倍。 学习排序算法不能仅仅停留在了解算法原理和使用代码实现这两步,我们应该在此基础上学会去分析和评价一个算法 。我们可以从以下几各方面去衡量一个排序算法: 对于排序算法执行效率的分析 ,包括最好、最坏、平均情况下的时间复杂度,算法运行过程中数据比较和交换的次数等。 对于排序算法的内存消耗分析 。算法的内存消耗通过空间复杂度来衡量。 排序算法的稳定性 。所谓稳定性,就是待排序的序列中的值相同的元素经过排序算法处理后是否保持原先的位置关系,若保持,则称这个排序算法为稳定的排序算法

排序与搜索

我的未来我决定 提交于 2019-12-04 11:25:13
排序与搜索 排序算法(英语:Sorting algorithm)是一种能将一串数据依照特定顺序进行排列的一种算法。 排序算法的稳定性 稳定性 :稳定排序算法会让原本有相等键值的纪录维持相对次序。也就是如果一个排序算法是稳定的,当有两个相等键值的纪录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) (次序被改变) 不稳定排序算法可能会在相等的键值中改变纪录的相对次序,但是稳定排序算法从来不会如此。不稳定排序算法可以被特别地实现为稳定。作这件事情的一个方式是人工扩充键值的比较,如此在其他方面相同键值的两个对象间之比较,(比如上面的比较中加入第二个标准:第二个键值的大小)就会被决定使用在原先数据次序中的条目,当作一个同分决赛。然而,要记住这种次序通常牵涉到额外的空间负担。 一、冒泡排序 冒泡排序 (英语:Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的数列