排序算法稳定性

数据结构和算法 (二)

不想你离开。 提交于 2019-11-28 13:48:24
数据结构(swift实现)一 1. 常用数据结构 1. 1 数组 1. 2 字典 1. 3 链表 1. 4 堆栈 1.4.1 堆 1.4.2 栈 1.5 队列 1.5.1 优先队列 1.5.2 循环队列 1.6 树 1.6.1 二叉树 1.6.2 二叉搜索树 1.6.3 平衡二叉树 1.7 图 2. 常用算法 2.1 查找算法 2.1.1 二分查找 2.1.2 广度优先搜索算法 2.1.3 深度优先搜索算法 2.2 排序算法 2.2.1 排序算法简介 2.2.2 排序算法比较 2.2.2.1 稳定性比较 2.2.2.2 时间复杂度比较 2.2.2.3 辅助空间比较 2.2.2.4 其他比较 2.2.3 排序算法实现 2.2.3.1 插入排序 2.2.3.2 选择排序 2.2.3.3 冒泡排序 2.2.3.4 快速排序 2.2.3.5 堆排序 2.2.3.6 归并排序 2.2.3.7 希尔排序 2.2.3.8 二叉树排序 2.2.3.9 计数排序 2.2.3.10 桶排序 2.2.3.11 基数排序 2.2.3.12 1. 常用数据结构 1. 1 数组 1. 2 字典 1. 3 链表 1. 4 堆栈 1.4.1 堆 1.4.2 栈 1.5 队列 1.5.1 优先队列 1.5.2 循环队列 1.6 树 1.6.1 二叉树 1.6.2 二叉搜索树 1.6.3 平衡二叉树 1.7 图 2.

排序应用

*爱你&永不变心* 提交于 2019-11-28 13:26:44
稳定性 如果一个排序算法能够保留数组中 重复元素的相对位置 则可以被称为是 稳定 的 稳定的排序算法:插入排序、归并排序 不稳定的排序算法:选择排序、希尔排序、快速排序和堆排序 一般只有在稳定性是必要的情况下,稳定的排序算法才有优势。 各种排序算法的性能特点 算法 是否稳定 是否为原地排序 时间复杂度 空间复杂度 备注 选择排序 否 是 N^2 1 插入排序 是 是 介于 N 和 N^2 之间 1 取决于输入元素的排列情况 希尔排序 否 是 NlogN? 1 快速排序 否 是 NlogN lgN 运行效率由概率提供保证 三向快速排序 否 是 介于 N 和 NlogN 之间 lgN 运行效率由概率保证,同时也取决于输入元素的分布情况 归并排序 是 否 NlogN N 堆排序 否 是 NlogN 1 快速排序是最快的通用排序算法。 如果稳定性重很重要而空见又不是问题,归并排序可能是最好的选择 Java 系统库的排序算法 Java 的系统程序员选择对 原始数据 类型使用(三向切分的)快速排序,对 引用类型 使用归并排序。暗示着用速度和空间(对于原始数据类型)来换取稳定性(对于引用类型)。 来源: https://www.cnblogs.com/aiguozou/p/11408905.html

面试常用算法之排序(1)

≯℡__Kan透↙ 提交于 2019-11-28 12:41:05
package algorithm.sort; /** * @Auther: AaronPi * @Date: 2019-4-27 23:01 * @Description: * 稳定性:待排序的序列中有想等值得元素排序后元素之间原有的先后顺序不变 * 原地排序算法:特指空间复杂度为O(1)的排序算法 */ public class BaseSort { /** * 冒泡排序:最多排序n次能出结果,第一次排序能找到最大数放在最后, * 如此反复第k次排序能找到排第k大的数,所以每次排序对前n-k个数排序即可,所以第k次找到n-k-1)个数即可。 * 并且,如果任何数据交换说明已经全部排好了,可以提前结束。 * * 空间复杂度O(1) ->原地排序算法 * 稳定的算法,相同大小不会改变顺序 * 平均时间复杂度为O(n^2) */ public static int[] bubbleSort(int[] array){ int n = array.length; boolean flag = false; if(n != 0 && n != 1){ for (int i = 0; i < n; ++i) { for (int j = 0; j < n-i-1; ++j) { if (array[j] > array[j + 1]) { int temp = array[j];

常用排序算法的稳定性分析

China☆狼群 提交于 2019-11-28 06:44:07
一、不稳定排序算法有哪些 1、堆排序 2、希尔排序 3、快速排序 4、选择排序 口诀: 一堆 (堆) 希尔 (希尔) 快 (快速) 选 (选择) 二、常见排序算法稳定性分析 1、堆排序稳定性分析 我们知道堆的结构是节点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 个相同的元素之间的稳定性就被破坏了。 所以,堆排序不是稳定的排序算法。 2、希尔排序 希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快; 当元素基本有序时,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比 O(N^2) 好一些。 由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序, 但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱

常见排序算法详解(冒泡、选择、插入、快速、希尔、归并)

自闭症网瘾萝莉.ら 提交于 2019-11-28 04:07:35
一、排序算法 1、冒泡排序(Bubble Sort) 定义 :是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。 原理: 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。 针对所有的元素重复以上的步骤,除了最后一个。 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 list1 = [12, 54, 23, 56, 67, 45, 1] def bubbleSort(): '''冒泡排序''' for i in range(len(list1) - 1, 0, -1): for j in range(i): if list1[j] > list1[j + 1]: list1[j], list1[j + 1] = list1[j + 1], list1[j] print(list1) bubbleSort() 时间复杂度: 最优时间复杂度:O(n) (表示遍历一次发现没有任何可以交换的元素,排序结束。) 最坏时间复杂度:O(n2) 稳定性:稳定 效果图: 2

归并排序

江枫思渺然 提交于 2019-11-27 15:22:44
1、什么是归并排序?   归并排序是属于分冶法的一种排序方式,归并排序将待排序的元素序列分成两个长度相等的子序列,为每一个子序列排序,然后再将他们合并成一个子序列。合并两个子序列的过程也就是两路归并。 2、时间复杂度和空间复杂度   归并排序是一种稳定的排序算法,一般用于对总体无序,但是各子项相对有序的数列。   归并排序的主要问题在于它需要一个与待排序数组一样大的辅助数组空间,所以空间复杂度为T(n)。   由于归并排序每次划分时两个子序列的长度基本一样,所以归并排序最好、最差和平均时间复杂度都是(nlogn)。 3、算法描述   将原本的待排序的数列不断的分解为两个子序列,直到子序列长度为1时开始合并   利用递归的方式分解数列   创建一个和原数组待排序字段长度一致的新数组,分别遍历字段的前半部分和后半部分取值,取其中较小的值   直到一部分遍历结束,将另一部分剩余的值全部赋予新数组   将新数组复制到原数组的待排序字段 4、java代码实现 public class Test { public static void main(String[] args) { // TODO Auto-generated method stub int[] A = {5,2,4,5,6,2,3,6,7,9}; sort(A,1,9);//第一个5不参加排序 for(int l=0;l<A

排序算法003-选择排序

☆樱花仙子☆ 提交于 2019-11-27 14:16:35
排序算法003- 选择排序 ----------------------------------------------------------- 算法原理: 选择排序就是从所有的数据中找到最小的值,依次和第一个、第二个、第三个……位置上的数据交换。 1)记录第一个为当做最小的值(其实,第一个不一定是最小值),然后 把剩余其他的数据都扫描一趟 从中挑出最小的值。把最小的值和数组的第一个数据交换,即放到0号位置。 2)记录第二个为最小值(第一个为最小值,此时忽略0号位置的值),然后扫描剩余其他数据挑出最小的值。把最小的值和数据的第二个数据交换,即放到1号位置。 3)重复以上步骤,依次放好2号、3号、4号位置上的值。 再次叙述, 假设有10个运动员,从左向右递增排序。 1)在本子上记录第一运动员的身高,并把红色标志Flag给第一个人。 2)拿第二个人的身高和本子上的身高比较,如果第二个人的身高较低,则划掉第一个人的身高,记录最小值为第二个人的身高,再把红色标志Flag给第二个人。否则,不更新。 3)依次拿第三个人的身高和记录比较,如果小,则更新最小值和移动flag(只移动,但是没有交换啊!!) 4)最后,本子上的记录为最小值,红色Flag为最小值对应的位置。 5)将红色Flag上的人(最小值)和第一个位置的人进行交换。 6)一次排序结束。重复以上步骤。 ----------------

排序算法--希尔排序

江枫思渺然 提交于 2019-11-27 14:15:24
备忘一下希尔排序。 原理: 希尔排序是插入排序的变种。希尔排序是基于插入排序的以下两点性质而提出改进方法的:插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。 借用百度百科的一段话,之所以希尔排序优于插入排序,原因是,当n值很大时数据项每一趟排序需要的个数很少,但数据项的距离很长。当n值减小时每一趟需要动的数据增多,此时已经接近于它们排序后的最终位置。 正是这两种情况的结合才使希尔排序效率比插入排序高很多。 分析: 至于稳定性,单个插入能保证稳定性,但是多组插入就不能保证组之间的稳定性了,所以它是不稳定的。时间复杂度方面, 好多 资料认为希尔排序时间复杂度会比o(n^2)好一些。空间方面,它是原地的。 代码展示 :我在这里使用的步长d初始为数组的长度的一半,然后不停减半直到1。 public class ShellSort { public static void main(String[] args){ int[] target = {49,38,65,97,76,13,27,49,78,34,12,64,1}; new ShellSort().shell_sort(target); System.out.print("Result:"+" "); for(int k : target)

排序算法--归并排序

风格不统一 提交于 2019-11-27 14:15:06
这次备忘一下归并排序。归并排序是分治方法的典型应用。 步骤 :1、把序列分成元素个数尽量相等的两半 2、把两半元素分别排序 3、把两个有续表合并 其中,分治使用的是递归,出口就是被分到的组元素个数小于等于1 分析 :先看时间复杂度,涉及二分的,一般就是O(nlogn)。稳定性方面,相等元素被分到二个组中,合并的时候并不会出现顺序颠倒,所以是稳定的。空间复杂度方面,需要一个临时存储数组,为O(N). 代码展示 : public class MergSort { public static void main(String[] args){ int[] target = {1,10,2,5,7,3,5,8}; int[] tmp = new int[target.length];//建一个临时存储数组 new MergSort().merg_sort(target, 0, target.length, tmp); System.out.print("Result:"+" "); for(int k : target) System.out.print(k+" "); } public void merg_sort(int[] target,int x,int y,int[] tmp){ if(y-x>1){//程序传进来的y是需要排序数组段最后一个元素的下一个元素下标 int m =

排序算法--插入排序

此生再无相见时 提交于 2019-11-27 14:14:29
继续备忘一个简单的排序算法--插入排序,并且仍旧对整数组成的数组进行升序排序。 原理: 同样基于元素比较进行排序。进行第N趟遍历的时候,前面N-1个元素已经有序,只需要从右向左逐个和已经排好序的元素比较,去寻找第N个元素可以插入的位置,找到之后插入即可。遍历N-1趟。 步骤: 初始化遍历指针i,j。i代表每次需要拿去插入的元素的下标,j遍历已经排过序的部分,找到应该插入的位置插入。直到i代表将所有元素都插入到应该插入的位置了。 分析: 时间复杂度方面,需要遍历n次,最好情况是已经升序排好,此时不需要移动元素,最坏的也就是逆序的时候,需要移动n(n-1)/2次,平均时间复杂度为O(n^2)。它也是原地排序。稳定性方面,因为每次插入的时候,只有前面的元素大于被插入元素才进行后移,所以是稳定的。 代码展示 : public class InsertSort { public static void main(String[] args){ int[] array = {7, 11, 5, 8, 7, 2, 10, 1}; System.out.print("待排序数组:");//打印排序之前的样子 for(int k : array) System.out.print(k + " "); System.out.println(); sort(array);//排序之中 System