排序算法稳定性

排序算法

岁酱吖の 提交于 2019-12-25 22:06:22
排序算法 排序的基本概念: 排序 :给定一组记录的集合{r1, r2, ……, rn},其相应的关键码分别为{k1, k2, ……, kn},排序是将这些记录排列成顺序为{rs1, rs2, ……, rsn}的一个序列,使得相应的关键码满足ks1≤ks2≤……≤ksn(称为升序)或ks1≥ks2≥……≥ksn(称为降序)。 正序 :待排序序列中的记录已按关键码排好序。 逆序(反序 ):待排序序列中记录的排列顺序与排好序的顺序正好相反。 趟 :在排序过程中,将待排序的记录序列扫描一遍称为一趟。通常,一次排序过程需要进行多趟扫描才能完成 排序算法的稳定性: 假定在待排序的记录集中,存在多个具有相同键值的记录,若经过排序,这些记录的相对次序仍然保持不变,即在原序列中,ki=kj且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的。 对于不稳定的排序算法,只要举出一个实例,即可说明它的不稳定性;而对于稳定的排序算法,必须对算法进行分析从而证明稳定的特性。 排序算法是否为稳定的是由具体算法决定的: 不稳定的算法在某种条件下可以变为稳定的算法, 而稳定的算法在某种条件下也可以变为不稳定的算法。 稳定性比较: 所有排序方法可分为两类, (1)一类是稳定的,包括直接插入排序、起泡排序、和归并排序,基数桶式排序; (2)另一类是不稳定的,包括直接选择排序

[常用排序算法] 希尔排序 (Shell Sort)

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-25 12:07:22
一 基本思想 希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,同时该算法是冲破O(n2)的第一批算法之一。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。 希尔排序是把元素按下表的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个数组被分成一组,算法便终止。 二 算法描述 来看下希尔排序的基本步骤,在此我们选择增量 gap = length / 2,缩小增量继续以 gap = gap / 2 的方式,这种增量选择我们可以用一个序列来表示,{n / 2, (n / 2) / 2 … 1},称为增量序列。希尔排序的增量序列的选择与证明是个数学难题,我们选择的这个增量序列是比较常用的,也是希尔建议的增量,称为希尔增量,但其实这个增量序列不是最优的。此处我们做示例使用希尔增量。 先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述: 选择一个增量序列 t1,t2,…,tk,其中 ti > tj,tk = 1; 按增量序列个数 k,对序列进行 k 趟排序; 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序

排序算法——冒泡排序

情到浓时终转凉″ 提交于 2019-12-23 10:54:36
一、介绍 冒泡排序(Bubble Sort),又被称为气泡排序或泡沫排序。 它是一种较简单的排序算法。它会遍历若干次要排序的数列,每次遍历时,它都会从前往后依次的比较相邻两个数的大小;如果前者比后者大,则交换它们的位置。这样,一次遍历之后,最大的元素就在数列的末尾! 采用相同的方法再次遍历时,第二大的元素就被排列在最大元素之前。重复此操作,直到整个数列都有序为止! 二、图文说明 下面以数列{20,40,30,10,60,50}为例,演示它的冒泡排序过程(如下图)。 我们先分析第1趟排序 当i=5,j=0时,a[0]<a[1]。此时,不做任何处理! 当i=5,j=1时,a[1]>a[2]。此时,交换a[1]和a[2]的值;交换之后,a[1]=30,a[2]=40。 当i=5,j=2时,a[2]>a[3]。此时,交换a[2]和a[3]的值;交换之后,a[2]=10,a[3]=40。 当i=5,j=3时,a[3]<a[4]。此时,不做任何处理! 当i=5,j=4时,a[4]>a[5]。此时,交换a[4]和a[5]的值;交换之后,a[4]=50,a[3]=60。 于是,第1趟排序完之后,数列{20,40,30,10,60,50}变成了{20,30,10,40,50,60}。此时,数列末尾的值最大。 根据这种方法: 第2趟排序完之后,数列中a[5...6]是有序的。 第3趟排序完之后

python算法

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

选择排序

空扰寡人 提交于 2019-12-18 02:37:54
选择排序 概要 本章介绍排序算法中的选择排序。 目录 1. 选择排序介绍 2. 选择排序图文说明 3. 选择排序的时间复杂度和稳定性 4. 选择排序实现 4.1 选择排序C实现 4.2 选择排序C++实现 4.3 选择排序Java实现 转载请注明出处: http://www.cnblogs.com/skywang12345/p/3597641.html 更多内容: 数据结构与算法系列 目录 选择排序介绍 选择排序(Selection sort)是一种简单直观的排序算法。 它的基本思想是:首先在未排序的数列中找到最小(or最大)元素,然后将其存放到数列的起始位置;接着,再从剩余未排序的元素中继续寻找最小(or最大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。 选择排序图文说明 选择排序代码 /* * 选择排序 * * 参数说明: * a -- 待排序的数组 * n -- 数组的长度 */ void select_sort(int a[], int n) { int i; // 有序区的末尾位置 int j; // 无序区的起始位置 int min; // 无序区中最小元素位置 for(i=0; i<n; i++) { min=i; // 找出"a[i+1] ... a[n]"之间的最小元素,并赋值给min。 for(j=i+1; j<n; j++) { if(a

浅谈算法和数据结构: 五 优先级队列与堆排序

邮差的信 提交于 2019-12-16 22:29:14
在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象。最简单的一个例子就是,在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话。 在这种情况下,我们的数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue) 。 本文首先介绍优先级队列的定义,有序和无序数组以及堆数据结构实现优先级队列,最后介绍了基于优先级队列的堆排序(Heap Sort) 一 定义 优先级队列和通常的栈和队列一样,只不过里面的每一个元素都有一个”优先级”,在处理的时候,首先处理优先级最高的。如果两个元素具有相同的优先级,则按照他们插入到队列中的先后顺序处理。 优先级队列可以通过链表,数组,堆或者其他数据结构实现。 二 实现 数组 最简单的优先级队列可以通过有序或者无序数组来实现,当要获取最大值的时候,对数组进行查找返回即可。代码实现起来也比较简单,这里就不列出来了。 如上图: · 如果使用无序数组,那么每一次插入的时候,直接在数组末尾插入即可,时间复杂度为O(1),但是如果要获取最大值,或者最小值返回的话,则需要进行查找,这时时间复杂度为O(n)。 · 如果使用有序数组,那么每一次插入的时候,通过插入排序将元素放到正确的位置,时间复杂度为O(n)

排序算法 ---- 插入排序

荒凉一梦 提交于 2019-12-15 22:24:40
插入排序 插入排序(英语:Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。 def insert_sort ( alist ) : "插入排序" n = len ( alist ) for j in range ( 1 , n ) : i = j while i > 0 : if alist [ i ] < alist [ i - 1 ] : alist [ i ] , alist [ i - 1 ] = alist [ i - 1 ] , alist [ i ] i -= 1 else : break if __name__ == '__main__' : alist = [ 54 , 26 , 93 , 17 , 77 , 17 , 44 , 55 , 20 ] insert_sort ( alist ) print ( alist ) # 时间复杂度 # 最优时间复杂度:O(n) (升序排列,序列已经处于升序状态) # 最坏时间复杂度:O(n2) # 稳定性:稳定 来源: CSDN 作者: 愤进的蜗牛 链接: https://blog.csdn.net/weixin

数据结构常见面试题

让人想犯罪 __ 提交于 2019-12-15 20:44:56
数据结构常见面试题 1、数组和链表的区别。 从逻辑结构上来看 ,数组必须实现定于固定的长度,不能适应数据动态增减的情况,即数组的大小一旦定义就不能改变。当数据增加是,可能超过原先定义的元素的个数;当数据减少时,造成内存浪费;链表动态进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。 从内存存储的角度看 ;数组从栈中分配空间(用new则在堆上创建),对程序员方便快速,但是自由度小;链表从堆中分配空间,自由度大但是申请管理比较麻烦。 从访问方式类看 ,数组在内存中是连续的存储,因此可以利用下标索引进行访问;链表是链式存储结构,在访问元素时候只能够通过线性方式由前到后顺序的访问,所以访问效率比数组要低。 2、简述快速排序过程 1)选择一个基准元素,通常选择第一个元素或者最后一个元素, 2)通过一趟排序将待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的元素值比基准值大。 3)此时基准元素在其排好序后的正确位置 4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。 3、快速排序的改进 只对长度大于k的子序列递归调用快速排序,让原序列基本有序,然后再对整个基本有序序列用插入排序算法排序。实践证明,改进后的算法时间复杂度有所降低,且当k取值为 8 左右时,改进算法的性能最佳。 选择基准元的方式 对于分治算法

java实现三种朴素排序算法

我是研究僧i 提交于 2019-12-15 01:38:48
三种朴素排序算法的java实现 1,冒泡排序: 特性 值 种类 比较排序 稳定性 稳定 时间复杂度 O(n 2 ) 空间复杂度 O(1) public static void bubbleSort ( int [ ] array ) { for ( int i = 0 ; i < array . length - 1 ; i ++ ) for ( int j = 0 , temp = 0 ; j < array . length - 1 ; j ++ ) { if ( array [ j ] > array [ j + 1 ] ) { temp = array [ j ] ; array [ j ] = array [ j + 1 ] ; array [ j + 1 ] = temp ; } } } 2,插入排序: 特性 值 种类 比较排序 稳定性 稳定 时间复杂度 O(n 2 ) 空间复杂度 O(1) public static void insertionSort ( int [ ] array ) { for ( int i = 1 ; i < array . length ; i ++ ) { for ( int j = i ; j > 0 && array [ j - 1 ] > array [ j ] ; j -- ) { int temp = array [ j -

直接选择排序(Straight Selection Sort)

假如想象 提交于 2019-12-13 17:49:59
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 1、定义 选择排序(Selection Sort)的基本思想是:每一趟从待排序的记录中选出关键字最小的记录,顺序放在已排好序的子文件的最后,直到全部记录排序完毕。 常用的选择排序方法有直接选择排序和堆排序。 2、基本思想 n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果: ① 初始状态:无序区为R[1..n],有序区为空。 ② 第1趟排序 在无序区R[1..n]中选出关键字最小的记录R[k],将它与无序区的第1个记录R[1]交换,使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。 …… ③ 第i趟排序 第i趟排序开始时,当前有序区和无序区分别为R[1..i-1]和R[i..n](1≤i≤n-1)。该趟排序从当前无序区中选出关键字最小的记录R[k],将它与无序区的第1个记录R[i]交换,使R[1..i]和R[i+1..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。 这样,n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果。 3、算法描述 直接选择排序的具体算法如下:   void SelectSort(SeqList R)  { int i,j,k; for(i=1;i<n;i++){//做第i趟排序(1≤i≤n