稳定排序和不稳定排序

合集下载

java稳定的排序方法

java稳定的排序方法

java稳定的排序方法
Java是一种广泛使用的编程语言,其中排序是常见的操作。

在排序中,稳定性是一个重要的概念。

稳定的排序算法可以保留相等元素的原始顺序,而不稳定的排序算法不保证这一点。

下面介绍几种Java中稳定的排序方法:
1. 冒泡排序:该算法的基本思想是通过交换相邻的元素来将较大的元素逐步“冒泡”到数组的末尾。

冒泡排序是一种简单但效率较低的排序算法,时间复杂度为O(n^2)。

2. 插入排序:该算法的基本思想是将数组分为有序和无序两部分,从无序部分依次取出一个元素插入到有序部分的适当位置。

插入排序的时间复杂度也是O(n^2),但在实际应用中,它比冒泡排序更常用。

3. 归并排序:该算法的基本思想是将待排序数组分成两个子数组,并将每个子数组递归地进行排序,然后再将它们合并成一个有序数组。

归并排序的时间复杂度为O(nlogn),但它需要额外的空间来存储子数组。

4. 堆排序:该算法的基本思想是将待排序数组构建为一个最大堆(或最小堆),然后不断取出堆顶元素并重新调整堆,直到所有元素都被取出。

堆排序的时间复杂度为O(nlogn),但也需要额外的空间来存储堆。

总的来说,以上排序方法都是稳定的。

在实际应用中,我们需要根据数据规模、数据类型和性能需求等因素来选择适当的排序算法。

各种排序的时间复杂度

各种排序的时间复杂度

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

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

一般而言,好的表现是O。

(n log n),且坏的行为是Ω(n2)。

对於一个排序理想的表现是O(n)。

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

记忆体使用量(以及其他电脑资源的使用)稳定度:稳定排序算法会依照相等的关键(换言之就是值)维持纪录的相对次序。

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

一般的方法:插入、交换、选择、合并等等。

交换排序包含冒泡排序(bubble sort)和快速排序(quicksort)。

选择排序包含shaker排序和堆排序(heapsort)。

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

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

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

不稳定排序算法可以被特别地时作为稳定。

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

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

排列算法列表在这个表格中,n是要被排序的纪录数量以及k是不同键值的数量。

稳定的冒泡排序(bubble sort)— O(n2)鸡尾酒排序 (Cocktail sort, 双向的冒泡排序) — O(n2)插入排序(insertion sort)— O(n2)桶排序(bucket sort)— O(n); 需要 O(k) 额外记忆体计数排序 (counting sort) — O(n+k); 需要 O(n+k) 额外记忆体归并排序(merge sort)— O(n log n); 需要 O(n) 额外记忆体原地归并排序— O(n2)二叉树排序(Binary tree sort)— O(n log n); 需要 O(n) 额外记忆体鸽巢排序 (Pigeonhole sort) — O(n+k); 需要 O(k) 额外记忆体基数排序(radix sort)—O(n·k); 需要 O(n) 额外记忆体Gnome sort — O(n2)Library sort — O(n log n) with high probability, 需要(1+ε)n 额外记忆体不稳定选择排序(selection sort)— O(n2)希尔排序(shell sort)— O(n log n) 如果使用最佳的现在版本Comb sort — O(n log n)堆排序(heapsort)— O(n log n)Smoothsort — O(n log n)快速排序(quicksort)—O(n log n) 期望时间, O(n2) 最坏情况; 对於大的、乱数串列一般相信是最快的已知排序Introsort — O(n log n)Patience sorting —O(n log n + k) 最外情况时间, 需要额外的 O(n + k) 空间, 也需要找到最长的递增子序列(longest increasing subsequence)不实用的排序算法Bogo排序—O(n × n!) 期望时间, 无穷的最坏情况。

十大经典排序算法总结

十大经典排序算法总结

⼗⼤经典排序算法总结最近⼏天在研究算法,将⼏种排序算法整理了⼀下,便于对这些排序算法进⾏⽐较,若有错误的地⽅,还请⼤家指正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)的第⼀批算法之⼀。

算法的时间复杂度和空间复杂度

算法的时间复杂度和空间复杂度

相关知识介绍(所有定义只为帮助读者理解相关概念,并非严格定义):1、稳定排序和非稳定排序简单地说就是所有相等的数经过某种排序方法后,仍能保持它们在排序之前的相对次序,我们就说这种排序方法是稳定的。

反之,就是非稳定的。

比如:一组数排序前是a1,a2,a3,a4,a5,其中a2=a4,经过某种排序后为a1,a2,a4,a3,a5,则我们说这种排序是稳定的,因为a2排序前在a4的前面,排序后它还是在a4的前面。

假如变成a1,a4, a2,a3,a5就不是稳定的了。

2、内排序和外排序在排序过程中,所有需要排序的数都在内存,并在内存中调整它们的存储顺序,称为内排序;在排序过程中,只有部分数被调入内存,并借助内存调整数在外存中的存放顺序排序方法称为外排序。

3、算法的时间复杂度和空间复杂度所谓算法的时间复杂度,是指执行算法所需要的计算工作量。

一个算法的空间复杂度,一般是指执行这个算法所需要的内存空间。

功能:选择排序输入:数组名称(也就是数组首地址)、数组中元素个数算法思想简单描述:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

选择排序是不稳定的。

算法复杂度O(n2)--[n的平方void select_sort(int *x, int n){int i, j, min, t;for (i=0; i<n-1; i++) /*要选择的次数:0~n-2共n-1次*/{min = i; /*假设当前下标为i的数最小,比较后再调整*/for (j=i+1; j<n; j++)/*循环找出最小的数的下标是哪个*/{if (*(x+j) < *(x+min)){min = j; /*如果后面的数比前面的小,则记下它的下标*/}}if (min != i) /*如果min在循环中改变了,就需要交换数据*/{t = *(x+i);*(x+i) = *(x+min);*(x+min) = t;}}/*功能:直接插入排序输入:数组名称(也就是数组首地址)、数组中元素个数算法思想简单描述:在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。

计算机软件技术编程基础 排序

计算机软件技术编程基础 排序

21
47
48
56
85
89
对于长度为n的序列,选择序列需要扫描n-1遍,每次扫 描均从剩余的子表中找出最小的元素,然后将最小的元 素与子表中的第一个元素进行交换。
比较次数:(n-1)+(n-2)+…+2+1=n(n-1)/2
交换次数:n-1 时间复杂度O(n2)
四 归并排序
基本思想:将两个或两个以上的有序表合并成一个新的有序表。 步骤: 将整个表看成n个有序子表,每个子表长度为1; 两两归并,得到长度为2的n/2个子表; 再两两归并,一直得到长度为n的有序表为止;
关键字最小的安置到最前面
对剩余的线性表重复操作 1 1 1 1 1 1 1 1 5 5 3 3 3 2 3 5 2 3 2 3 2 2 52 5 4 5 6 6 6 56 4 7 4 7 4 6 4 4 6 8 8 8 8 9 9 9 9
74 7 6 6 6 6 7 7
1
1
2
3
4
5
6
6
7
8
9
对线性表的每次来回操作都将最大的沉到表底,最小的像气 泡冒到表头。
2 希尔排序——缩小增量排序
基本步骤: 1 取一个正整数h1=n/2, 每隔步长h1取一个元素,放在一个组中,在 各组中进行插入排序。
0
7
1
19
2
24
3
13
4
31
5
8
6
82
7
18
8
44
9
63
10
5
11
29
h1=12/2
7 19 24 13 31 8 82 18 44 63 5 29

数据结构答案 第10章 排序学习与指导

数据结构答案 第10章 排序学习与指导

第10章排序10.1 知识点分析1.排序基本概念:(1)排序将数据元素的任意序列,重新排列成一个按关键字有序(递增或递减)的序列的过程称为排序。

(2)排序方法的稳定和不稳定若对任意的数据元素序列,使用某个排序方法,对它按关键字进行排序,若对原先具有相同键值元素间的位置关系,排序前与排序后保持一致,称此排序方法是稳定的;反之,则称为不稳定的。

(3)内排序整个排序过程都在内存进行的排序称为内排序,本书仅讨论内排序。

(4)外排序待排序的数据元素量大,以致内存一次不能容纳全部记录,在排序过程中需要对外存进行访问的排序称为外排序。

2.直接插入排序直接插入排序法是将一个记录插到已排序好的有序表中,从而得到一个新的,记录数增1的有序表。

3.二分插入排序二分插入排序法是用二分查找法在有序表中找到正确的插入位置,然后移动记录,空出插入位置,再进行插入的排序方法。

4.希尔排序希尔排序的基本思想是:先选取一个小于n的整数d1作为第一个增量,把待排序的数据分成d1个组,所有距离为d1的倍数的记录放在同一个组内,在各组内进行直接插入排序,每一趟排序会使数据更接近于有序。

然后,取第二个增量d2,d2< d1,重复进行上述分组和排序,直至所取的增量d i=1(其中d i< d i-1 < ……< d2< d1),即所有记录在同一组进行直接插入排序后为止。

5.冒泡排序冒泡法是指每相邻两个记录关键字比大小,大的记录往下沉(也可以小的往上浮)。

每一遍把最后一个下沉的位置记下,下一遍只需检查比较到此为止;到所有记录都不发生下沉时,整个过程结束。

6.快速排序快速排序法是通过一趟排序,将待排序的记录组分割成独立的两部分,其中前一部分记录的关键字均比枢轴记录的关键字小;后一部分记录的关键字均比枢轴记录的关键字大,枢轴记录得到了它在整个序列中的最终位置并被存放好。

第二趟再分别对分割成两部分子序列,再进行快速排序,这两部分子序列中的枢轴记录也得到了最终在序列中的位置而被存放好,并且它们又分别分割出独立的两个子序列……。

排序—时间复杂度为O(n2)的三种排序算法

排序—时间复杂度为O(n2)的三种排序算法

排序—时间复杂度为O(n2)的三种排序算法1 如何评价、分析⼀个排序算法?很多语⾔、数据库都已经封装了关于排序算法的实现代码。

所以我们学习排序算法⽬的更多的不是为了去实现这些代码,⽽是灵活的应⽤这些算法和解决更为复杂的问题,所以更重要的是学会如何评价、分析⼀个排序算法并在合适的场景下正确使⽤。

分析⼀个排序算法,主要从以下3个⽅⾯⼊⼿:1.1 排序算法的执⾏效率1)最好情况、最坏情况和平均情况时间复杂度待排序数据的有序度对排序算法的执⾏效率有很⼤影响,所以分析时要区分这三种时间复杂度。

除了时间复杂度分析,还要知道最好、最坏情况复杂度对应的要排序的原始数据是什么样的。

2)时间复杂度的系数、常数和低阶时间复杂度反映的是算法执⾏时间随数据规模变⼤的⼀个增长趋势,平时分析时往往忽略系数、常数和低阶。

但如果我们排序的数据规模很⼩,在对同⼀阶时间复杂度的排序算法⽐较时,就要把它们考虑进来。

3)⽐较次数和交换(移动)次数内排序算法中,主要进⾏⽐较和交换(移动)两项操作,所以⾼效的内排序算法应该具有尽可能少的⽐较次数和交换次数。

1.2 排序算法的内存消耗也就是分析算法的空间复杂度。

这⾥还有⼀个概念—原地排序,指的是空间复杂度为O(1)的排序算法。

1.3 稳定性如果待排序的序列中存在值相等的元素,经过排序之后,相等元素之间原有的先后顺序不变,那么这种排序算法叫做稳定的排序算法;如果前后顺序发⽣变化,那么对应的排序算法就是不稳定的排序算法。

在实际的排序应⽤中,往往不是对单⼀关键值进⾏排序,⽽是要求排序结果对所有的关键值都有序。

所以,稳定的排序算法往往适⽤场景更⼴。

2 三种时间复杂度为O(n2)的排序算法2.1 冒泡排序2.1.1 原理两两⽐较相邻元素是否有序,如果逆序则交换两个元素,直到没有逆序的数据元素为⽌。

每次冒泡都会⾄少让⼀个元素移动到它应该在的位置。

2.1.2 实现void BubbleSort(int *pData, int n) //冒泡排序{int temp = 0;bool orderlyFlag = false; //序列是否有序标志for (int i = 0; i < n && !orderlyFlag; ++i) //执⾏n次冒泡{orderlyFlag = true;for (int j = 0; j < n - 1 - i; ++j) //注意循环终⽌条件{if (pData[j] > pData[j + 1]) //逆序{orderlyFlag = false;temp = pData[j];pData[j] = pData[j + 1];pData[j + 1] = temp;}}}}测试结果2.1.3 算法分析1)时间复杂度最好情况时间复杂度:当待排序列已有序时,只需⼀次冒泡即可。

7排序

7排序

数据结构
例: 初始
49 38 65 97 76 13 27
48
55
4
取d1=5 一趟分组:49 38 65 97 76 13 27
48
55
4
一趟排序:13 27 48 55 4
49 38
65
97
76
取d2=3 13 27 48 55 4 二趟分组:
49 38
65
97
76
二趟排序:13
4
48 38 27
做出相应的调整,那样排序的总体效率会非常高。
• 堆排序(Heap Sort)就是对简单选择排序的一种改进。堆排序 算法是Floyd和Williams在1964年共同发明,同时发明了“堆” 这样的数据结构。
数据结构
堆的定义
一、定义
16 11 9
10 1 2
2
5 4
6
大顶堆
8
1
6 9
小顶堆
数据结构
11 4 12 16 5
• R[0]为监视哨(Sentinel),省略下标越界检查“j>0”:一 旦越界,j=0<1,循环条件R[0]<R[j]不成立,自动控制 while循环的结束。
例:有监视哨,第3趟
0 1 2 3 4 5 6 7 8 9 10 m
初始:
i=3: j=2: j=1: j=0:
49 38 13 76 27 49 38 49 13 76 27 49 13 38 49 13 76 27 49 13 38 49 49 76 27 49 13 38 38 49 76 27 49 13 13 38 49 76 27 49
8
堆的定义
一、定义 • 堆是具有下列性质的完全二叉树:任一结点关键字大于等于 其孩子结点的关键字,称为大顶堆;任一结点关键字小于等 于其孩子结点的关键字,称为小顶堆。 • 将R[1]到R[n]看成完全二叉树的顺序存储结构。根据二叉树 的性质5,如果双亲下标为i,其左右孩子的下标分别为2i和 2i+1. 当且仅当任一R[i]满足以下关系时,称之为堆: R[i] ≤ R[2i]且R[i] ≤ R[2i+1] (1 ≤ i ≤ n/2) 或者 R[i] ≥ R[2i]且R[i] ≥ R[2i+1] (1 ≤ i ≤ n/2) 且分别称之为小顶堆和大顶堆。

排序

排序

13
13
d=4 j
21
40
j
16
i
21
40 25
希尔排序
希尔插入排序过程示例
1 初始序列 40 08 40 2 25 25 3 49 49 4 25* 25* 5 16 16 6 21 21 7 08 08 8 30 30 9
13
13
d=4
j
j
16
i
08 40 25 49
21
希尔排序
希尔插入排序过程示例
快速排序
关键问题⑴:如何选择轴值? 选择轴值的方法: 1.使用第一个记录的关键码; 2.选取序列中间记录的关键码; 3.比较序列中第一个记录、最后一个记录和中间 记录的关键码,取关键码居中的作为轴值并调 换到第一个记录的位置; 4.随机选取轴值。
选取不同轴值的后果:
决定两个子序列的长度,子序列的长度最好相等。
1 初始序列 40 2 25 25 3 49 49 4 25* 25* 5 16 16 6 21 21 7 08 08 8 30 30 9
13
13
d=4
30
40
j
16
i
25* 40 25 49 30
21
08
希尔排序
希尔插入排序过程示例
1 初始序列 40 13 40 2 25 25 3 49 49 4 25* 25* 5 16 16 6 21 21 7 08 08 8 30 30 9
关键问题⑵:如何实现一次划分?
38 i
27
55
50
13
49
65 j
65 j
j
13
27
i
55
50
38

数据结构排序中的稳定性和不稳定性

数据结构排序中的稳定性和不稳定性

稳定排序和不稳定排序这几天笔试了好几次了,连续碰到一个关于常见排序算法稳定性判别的问题,往往还是多选,对于我以及和我一样拿不准的同学可不是一个能轻易下结论的题目,当然如果你笔试之前已经记住了数据结构书上哪些是稳定的,哪些不是稳定的,做起来应该可以轻松搞定。

本文是针对老是记不住这个或者想真正明白到底为什么是稳定或者不稳定的人准备的。

首先,排序算法的稳定性大家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。

在简单形式化一下,如果Ai = Aj,Ai 原来在位置前,排序后Ai还是要在Aj位置前。

其次,说一下稳定性的好处。

排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。

基数排序就是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。

另外,如果排序算法稳定,对基于比较的排序算法而言,元素交换的次数可能会少一些(个人感觉,没有证实)。

回到主题,现在分析一下常见的排序算法的稳定性,每个都给出简单的理由。

(1)冒泡排序冒泡排序就是把小的元素往前调或者把大的元素往后调。

比较是相邻的两个元素比较,交换也发生在这两个元素之间。

所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

(2)选择排序选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n - 1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。

那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。

比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。

几种排序的算法时间复杂度比较

几种排序的算法时间复杂度比较

几种排序的算法时间复杂度比较1.选择排序:不稳定,时间复杂度 O(n^2)选择排序的基本思想是对待排序的记录序列进行n-1遍的处理,第i遍处理是将L[i..n]中最小者与L[i]交换位置。

这样,经过i遍处理之后,前i个记录的位置已经是正确的了。

2.插入排序:稳定,时间复杂度 O(n^2)插入排序的基本思想是,经过i-1遍处理后,L[1..i-1]己排好序。

第i遍处理仅将L[i]插入L[1..i-1]的适当位置,使得L[1..i] 又是排好序的序列。

要达到这个目的,我们可以用顺序比较的方法。

首先比较L[i]和L[i-1],如果L[i-1]≤ L[i],则L[1..i]已排好序,第i遍处理就结束了;否则交换L[i]与L[i-1]的位置,继续比较L[i-1]和L[i-2],直到找到某一个位置j(1≤j≤i-1),使得L[j] ≤L[j+1]时为止。

图1演示了对4个元素进行插入排序的过程,共需要(a),(b),(c)三次插入。

3.冒泡排序:稳定,时间复杂度 O(n^2)冒泡排序方法是最简单的排序方法。

这种方法的基本思想是,将待排序的元素看作是竖着排列的“气泡”,较小的元素比较轻,从而要往上浮。

在冒泡排序算法中我们要对这个“气泡”序列处理若干遍。

所谓一遍处理,就是自底向上检查一遍这个序列,并时刻注意两个相邻的元素的顺序是否正确。

如果发现两个相邻元素的顺序不对,即“轻”的元素在下面,就交换它们的位置。

显然,处理一遍之后,“最轻”的元素就浮到了最高位置;处理二遍之后,“次轻”的元素就浮到了次高位置。

在作第二遍处理时,由于最高位置上的元素已是“最轻”元素,所以不必检查。

一般地,第i遍处理时,不必检查第i高位置以上的元素,因为经过前面i-1遍的处理,它们已正确地排好序。

4.堆排序:不稳定,时间复杂度 O(nlog n)堆排序是一种树形选择排序,在排序过程中,将A[n]看成是完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。

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

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

【十大经典排序算法(动图演示)】必学十大经典排序算法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)是一种简单直观的排序算法。

排序算法稳定性比较

排序算法稳定性比较

这几天笔试了好几次了,连续碰到一个关于常见排序算法稳定性判别的问题,往往还是多选,对于我以及和我一样拿不准的同学可不是一个能轻易下结论的题目,当然如果你笔试之前已经记住了数据结构书上哪些是稳定的,哪些不是稳定的,做起来应该可以轻松搞定。

本文是针对老是记不住这个或者想真正明白到底为什么是稳定或者不稳定的人准备的。

首先,排序算法的稳定性大家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。

在简单形式化一下,如果Ai = Aj, Ai原来在位置前,排序后Ai还是要在Aj位置前。

其次,说一下稳定性的好处。

排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。

基数排序就是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。

另外,如果排序算法稳定,对基于比较的排序算法而言,元素交换的次数可能会少一些(个人感觉,没有证实)。

回到主题,现在分析一下常见的排序算法的稳定性,每个都给出简单的理由。

(1)冒泡排序冒泡排序就是把小的元素往前调或者把大的元素往后调。

比较是相邻的两个元素比较,交换也发生在这两个元素之间。

所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

(2)选择排序选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。

那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。

比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。

排序算法分类

排序算法分类

排序算法分类引⾃:https:///onepixel/articles/7674659.html0、算法概述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 代码实现2、选择排序(Selection Sort )选择排序(Selection-sort)是⼀种简单直观的排序算法。

它的⼯作原理:⾸先在未排序序列中找到最⼩(⼤)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最⼩(⼤)元素,然后放到已排序序列的末尾。

以此类推,直到所有元素均排序完毕。

排序算法总结

排序算法总结

排序算法总结【篇一:排序算法总结】1、稳定排序和非稳定排序简单地说就是所有相等的数经过某种排序方法后,仍能保持它们在排序之前的相对次序,我们就说这种排序方法是稳定的。

反之,就是非稳定的。

比如:一组数排序前是a1,a2,a3,a4,a5,其中a2=a4,经过某种排序后为a1,a2,a4,a3,a5,则我们说这种排序是稳定的,因为a2排序前在a4的前面,排序后它还是在a4的前面。

假如变成a1,a4,a2,a3,a5就不是稳定的了。

2、内排序和外排序在排序过程中,所有需要排序的数都在内存,并在内存中调整它们的存储顺序,称为内排序;在排序过程中,只有部分数被调入内存,并借助内存调整数在外存中的存放顺序排序方法称为外排序。

3、算法的时间复杂度和空间复杂度所谓算法的时间复杂度,是指执行算法所需要的计算工作量。

一个算法的空间复杂度,一般是指执行这个算法所需要的内存空间。

功能:选择排序输入:数组名称(也就是数组首地址)、数组中元素个数算法思想简单描述:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

选择排序是不稳定的。

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

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

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

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

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

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

一般的方法:插入、交换、选择、合并等等。

交换排序包含冒泡排序和快速排序。

判断数组是否稳定 公式

判断数组是否稳定 公式

判断数组是否稳定公式1. 引言1.1 什么是数组的稳定性数组的稳定性是指在排序过程中相同元素的相对位置是否发生改变。

在排序算法中,如果输入数组中有两个相同元素a和b,且在排序后a仍然在b前面,那么就可以说这个排序算法是稳定的。

换句话说,稳定的排序算法会保持相同元素的原有顺序。

举个例子来说明数组的稳定性:假设有一个包含相同元素的数组[4, 3, 2, 1, 4],如果使用稳定的排序算法对其进行排序,那么排序后的数组可能会是[1, 2, 3, 4, 4],其中两个4的相对位置没有发生改变。

数组的稳定性在实际应用中非常重要,特别是在需要保持元素原有顺序的情况下。

在对学生成绩进行排序时,如果两个学生有相同的成绩,那么排序后仍然希望他们保持原有的排名。

在对多个条件进行排序时,稳定性也能够帮助我们更好地理解排序结果。

了解和判断数组的稳定性是非常有必要的,它可以帮助我们选择合适的排序算法,确保排序结果符合我们的需求。

接下来我们将进一步探讨如何判断数组是否稳定以及稳定性的重要性。

1.2 为什么需要判断数组是否稳定数组的稳定性在排序算法中起着至关重要的作用。

在很多实际应用中,我们需要保持数组中元素的相对位置不变。

在对学生进行成绩排序时,如果有多个学生成绩相同,我们希望他们在排序后的数组中仍然保持原来的相对顺序。

这就需要使用稳定的排序算法来实现。

在对数据进行多次排序时,如果我们希望保持之前的排序结果不变,就需要使用稳定的排序算法。

而如果使用非稳定的排序算法,可能会导致之前的排序结果被打乱,从而影响到后续的操作。

需要判断数组是否稳定是非常必要的。

通过判断数组的稳定性,我们可以选择合适的排序算法来满足实际需求,并确保排序结果的准确性和稳定性。

深入理解数组的稳定性也有助于我们对排序算法的设计和优化有更深入的认识,提高程序的效率和性能。

为了保证程序的正确性和效率,我们需要对数组的稳定性进行准确的判断和分析。

2. 正文2.1 什么是稳定的排序算法稳定的排序算法是指在排序过程中,对于相等元素的相对位置不发生改变的排序算法。

各种排序算法的稳定性和时间复杂度小结

各种排序算法的稳定性和时间复杂度小结

各种排序算法的稳定性和时间复杂度小结选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。

冒泡法:这是最原始,也是众所周知的最慢的算法了。

他的名字的由来因为它的工作看来象是冒泡:复杂度为O(n*n)。

当数据为正序,将不会有交换。

复杂度为O(0)。

直接插入排序:O(n*n)选择排序:O(n*n)快速排序:平均时间复杂度log2(n)*n,所有内部排序方法中最高好的,大多数情况下总是最好的。

归并排序:log2(n)*n堆排序:log2(n)*n希尔排序:算法的复杂度为n的1.2次幂关于快速排序分析这里我没有给出行为的分析,因为这个很简单,我们直接来分析算法:首先我们考虑最理想的情况1.数组的大小是2的幂,这样分下去始终可以被2整除。

假设为2的k次方,即k=log2(n)。

2.每次我们选择的值刚好是中间值,这样,数组才可以被等分。

第一层递归,循环n次,第二层循环2*(n/2)......所以共有n+2(n/2)+4(n/4)+...+n*(n/n) = n+n+n+...+n=k*n=log2(n)*n所以算法复杂度为O(log2(n)*n)其他的情况只会比这种情况差,最差的情况是每次选择到的middle都是最小值或最大值,那么他将变成交换法(由于使用了递归,情况更糟)。

但是你认为这种情况发生的几率有多大??呵呵,你完全不必担心这个问题。

实践证明,大多数的情况,快速排序总是最好的。

如果你担心这个问题,你可以使用堆排序,这是一种稳定的O(log2(n)*n)算法,但是通常情况下速度要慢于快速排序(因为要重组堆)。

本文是针对老是记不住这个或者想真正明白到底为什么是稳定或者不稳定的人准备的。

首先,排序算法的稳定性大家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。

在简单形式化一下,如果Ai = Aj, Ai原来在位置前,排序后Ai还是要在Aj位置前。

基数排序稳定吗

基数排序稳定吗

基数排序稳定吗
1.稳定。

基数排序是按照低位先排序,然后收集;再按照高位
排序,然后再收集;依次类推,直到最高位。

有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。

2.基数排序、计数排序、插入排序、冒泡排序、归并排序等
是稳定排序。

选择排序、堆排序、快速排序、希尔排序等不是稳定排序。

3.:假定在待排序的记录序列中,存在多个具有相同的关键
字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且 r[i]在 r[j]之前,而在排序后的序列中,r[i]仍在 r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。

稳定排序和不稳定排序

稳定排序和不稳定排序

ቤተ መጻሕፍቲ ባይዱ
有序小序列中逐个插入元素从小序列末端开始比较这样元素的相对位置是不变的
稳定排序和不稳定排序
1. 稳定排序 Bubble Sort: 只比较相邻元素,相同就不换。 Insertion Sort:有序小序列中逐个插入元素,从小序列末端开始比较,这样元素的相对位置是不变的。 Merge Sort:大小不变不换,相对位置不变 基数排序:低位先排,再收集,直到高位。稳定。 2. 不稳定排序 Selection Sort:每个位置选当前元素最小的,这样元素排序依靠相对位置, Quick Sort:快排会打乱相同元素顺序(反过来) Hash Sort Heap Sort:父节点选择元素会破坏稳定性,父节点交换会打乱顺序

稳定排序和不稳定排序

稳定排序和不稳定排序

稳定排序和不稳定排序这⼏天笔试了好⼏次了,连续碰到⼀个关于常见排序算法稳定性判别的问题,往往还是多选,对于我以及和我⼀样拿不准的同学可不是⼀个能轻易下结论的题⽬,当然如果你笔试之前已经记住了数据结构书上哪些是稳定的,哪些不是稳定的,做起来应该可以轻松搞定。

本⽂是针对⽼是记不住这个或者想真正明⽩到底为什么是稳定或者不稳定的⼈准备的。

⾸先,排序算法的稳定性⼤家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。

在简单形式化⼀下,如果Ai = Aj,Ai原来在位置前,排序后Ai还是要在Aj位置前。

其次,说⼀下稳定性的好处。

排序算法如果是稳定的,那么从⼀个键上排序,然后再从另⼀个键上排序,第⼀个键排序的结果可以为第⼆个键排序所⽤。

基数排序就是这样,先按低位排序,逐次按⾼位排序,低位相同的元素其顺序再⾼位也相同时是不会改变的。

另外,如果排序算法稳定,对基于⽐较的排序算法⽽⾔,元素交换的次数可能会少⼀些(个⼈感觉,没有证实)。

回到主题,现在分析⼀下常见的排序算法的稳定性,每个都给出简单的理由。

(1)冒泡排序冒泡排序就是把⼩的元素往前调或者把⼤的元素往后调。

⽐较是相邻的两个元素⽐较,交换也发⽣在这两个元素之间。

所以,如果两个元素相等,我想你是不会再⽆聊地把他们俩交换⼀下的;如果两个相等的元素没有相邻,那么即使通过前⾯的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是⼀种稳定排序算法。

(2)选择排序选择排序是给每个位置选择当前元素最⼩的,⽐如给第⼀个位置选择最⼩的,在剩余元素⾥⾯给第⼆个元素选择第⼆⼩的,依次类推,直到第n - 1个元素,第n个元素不⽤选择了,因为只剩下它⼀个最⼤的元素了。

那么,在⼀趟选择,如果当前元素⽐⼀个元素⼩,⽽该⼩的元素⼜出现在⼀个和当前元素相等的元素后⾯,那么交换后稳定性就被破坏了。

⽐较拗⼝,举个例⼦,序列5 8 5 2 9,我们知道第⼀遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是⼀个稳定的排序算法。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

稳定排序和不稳定排序
这几天笔试了好几次了,连续碰到一个关于常见排序算法稳定性判别的问题,往往还是多选,对于我以及和我一样拿不准的同学可不是一个能轻易下结论的题目,当然如果你笔试之前已经记住了数据结构书上哪些是稳定的,哪些不是稳定的,做起来应该可以轻松搞定。

本文是针对老是记不住这个或者想真正明白到底为什么是稳定或者不稳定的人准备的。

首先,排序算法的稳定性大家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。

在简单形式化一下,如果Ai = Aj, Ai原来在位置前,排序后Ai还是要在Aj位置前。

其次,说一下稳定性的好处。

排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。

基数排序就是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。

另外,如果排序算法稳定,对基于比较的排序算法而言,元素交换的次数可能会少一些(个人感觉,没有证实)。

回到主题,现在分析一下常见的排序算法的稳定性,每个都给出简单的理由。

(1)冒泡排序
冒泡排序就是把小的元素往前调或者把大的元素往后调。

比较是相邻的两个元素比较,交换也发生在这两个元素之间。

所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

(2)选择排序
选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。

那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。

比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。

(3)插入排序
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。

当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。

比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。

如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。

所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。

(4)快速排序
快速排序有两个方向,左边的i下标一直往右走,当a[i] <= a[center_index],其中center_index是中枢元素的数组下标,一般取为数组第0个元素。

而右边的j下标一直往左走,当a[j] > a[center_index]。

如果i和j都走不动了,i <= j, 交换a[i]和a[j],重复上面的过程,直到i>j。

交换a[j]和a[center_index],完成一趟快速排序。

在中枢元素和a[j]交换的时
候,很有可能把前面的元素的稳定性打乱,比如序列为5 3 3 4 3 8 9 10 11,现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j] 交换的时刻。

(5)归并排序
归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。

可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定性。

那么,在短的有序序列合并的过程中,稳定是是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性。

所以,归并排序也是稳定的排序算法。

(6)基数排序
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。

有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序,最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。

基数排序基于分别排序,分别收集,所以其是稳定的排序算法。

(7)希尔排序(shell)
希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。

所以,希尔排序的时间复杂度会比o(n^2)好一些。

由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。

(8)堆排序
我们知道堆的结构是节点i的孩子为2*i和2*i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。

在一个长为n 的序列,堆排序的过程是从第n/2开始和其子节点共3个值选择最大(大顶堆)或者最小(小顶堆),这3个元素之间的选择当然不会破坏稳定性。

但当为n /2-1, n/2-2, ...1这些个父节点选择元素时,就会破坏稳定性。

有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没有交换,那么这2个相同的元素之间的稳定性就被破坏了。

所以,堆排序不是稳定的排序算法。

综上,得出结论: 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。

相关文档
最新文档