排序算法稳定性

常见排序算法汇总与分析(下)(基数排序与计数排序)

*爱你&永不变心* 提交于 2020-03-21 05:07:36
转载请注明出处: http://blog.csdn.net/fightlei/article/details/52586814 本篇汇总的算法将不再是基于比较的排序算法,因此会突破这类算法的时间复杂度下界O(nlog 2 n)。如果有朋友对前面的内容感兴趣,可以先去看看 常见排序算法汇总与分析(中)(选择排序与归并排序) 我们先来总结基数排序算法,该算法在排序过程中不进行比较,而是通过“分配”和“收集”两个过程来实现的。 基数排序 【基本思想】 首先设立r个队列,对列编号分别为0~r-1,r为待排序列中元素的基数(例如10进制数,则r=10),然后按照下面的规则对元素进行分配收集 1,先按最低有效位的值,把n个元素分配到上述的r个队列中,然后从小到大将个队列中的元素依次收集起来 2,再按次低有效位的值把刚收集起来的关键字分配到r个队列中,重复收集工作 3,重复地进行上述分配和收集,直到最高有效位。(也就是说,如果位数为d,则需要重复进行d次,d由所有元素中最长的一个元素的位数计量) 为什么这样就可以完成排序呢? 以从小到大排序为例 首先当按照最低有效位完成分配和收集后,此时得到的序列,是根据元素最低有效位的值从小到大排列的。 当按照次低有效位进行第二次分配和收集后,得到的序列,是先根据元素的次低有效位的值从小到大排列,然后再根据最低有效位的值从小到大排列。 以此类推

[C++面试题]之冒泡排序

|▌冷眼眸甩不掉的悲伤 提交于 2020-03-19 17:23:20
1、排序方法 将被排序的记录数组R[1..n]垂直排列,每个记录R[i]看作是重量为R[i].key的气泡。根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R:凡扫描到违反本原则的轻气泡,就使其向上"飘浮"。如此反复进行,直到最后任何两个气泡都是轻者在上,重者在下为止。 (1)初始 R[1..n]为无序区。 (2)第一趟扫描 从无序区底部向上依次比较相邻的两个气泡的重量,若发现轻者在下、重者在上,则交换二者的位置。即依次比较(R[n],R[n-1]),(R[n-1],R[n-2]),…,(R[2],R[1]);对于每对气泡(R[j+1],R[j]),若R[j+1].key<R[j].key,则交换R[j+1]和R[j]的内容。 第一趟扫描完毕时,"最轻"的气泡就飘浮到该区间的顶部,即关键字最小的记录被放在最高位置R[1]上。 (3)第二趟扫描 扫描R[2..n]。扫描完毕时,"次轻"的气泡飘浮到R[2]的位置上…… 最后,经过n-1 趟扫描可得到有序区R[1..n] 注意: 第i趟扫描时,R[1..i-1]和R[i..n]分别为当前的有序区和无序区。扫描仍是从无序区底部向上直至该区顶部。扫描完毕时,该区中最轻气泡飘浮到顶部位置R[i]上,结果是R[1..i]变为新的有序区。 2、冒泡排序过程示例 对关键字序列为49 38 65 97 76 13 27 49

十种排序算法

不羁的心 提交于 2020-03-18 17:36:29
3 月,跳不动了?>>> 排序 冒泡排序 排序过程 1、已知数组的长度为n,假定排序的总趟数为t,则t=n-1 2、第i趟(i取值范围[1,n-1])从第0个元素开始直到第n-i个元素,逐一向后每两个相邻的元素相互比较交换,保证最大(或者最小)值在后面 3、i++之后重复第二步 时间复杂度 最坏:n(n^2) 最好:n(n) 空间复杂度 一次基础临时变量赋值,所以空间复杂度为O(1) 稳定性 相邻数据之间的交换,所以是【稳定排序】 代码实现 public List<Integer> sort(List<Integer> list) { int size = 0; if(list == null || (size = list.size()) <= 1){ return list; } //总趟数 int t = size - 1; for (int i = 1; i <= t; i++) { boolean sorted = true; for (int j = 0; j < size - i; j++) { if (list.get(j) <= list.get(j + 1)) { continue; } //前面的比后面的大,需要交换 Integer temp = list.get(j); list.set(j, list.get(j + 1)); list.set(j + 1

排序算法之选择排序

随声附和 提交于 2020-03-17 17:28:00
基本思想: 在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换; 第二次遍历n-2个数,找到最小的数值与第二个元素交换; 。。。 第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成。 平均时间复杂度: O(n2) 过程: 代码: public int[] selectSort(int[] array){ for(int i = 0;i < array.length - 1;i++){ int minindex = i; for(int j = i + 1; j < array.length;j++){ if(array[j] < array[minindex]){ minindex = j; } } if(minindex != i){ array[i] = array[i] ^ array[minindex]; array[minindex] = array[i] ^ array[minindex]; array[i] = array[i] ^ array[minindex]; } } return array; }   总结: 时间复杂度 : 选择排序的交换操作介于 0 和 (n - 1) 次之间。选择排序的比较操作为 n (n - 1) / 2 次之间,比较次数O(n^2),比较次数与关键字的初始状态无关,总的比较次数N=(n-1)+(n

排序算法--持续更新

≡放荡痞女 提交于 2020-03-17 10:54:16
参考文献: https://mp.weixin.qq.com/s/vn3KiV-ez79FmbZ36SX9lg (将参考文章java代码用c/c++改写) 排序算法可以分为 内部排序 和 外部排序 。 内部排序 是数据记录在内存中进行排序。 外部排序 是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。 常见的内部排序算法有: 插入排序 、 希尔排序 、 选择排序 、 冒泡排序 、 归并排序 、 快速排序 、 堆排序 、 基数排序 等。 关于时间复杂度: 平方阶 (O(n2)) 排序 各类简单排序:直接插入、直接选择和冒泡排序。 线性对数阶 (O(nlog2n)) 排序 快速排序、堆排序和归并排序; O(n1+§)) 排序,§ 是介于 0 和 1 之间的常数。 希尔排序 线性阶 (O(n)) 排序 基数排序,此外还有桶、箱排序。 关于稳定性: 稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序。 不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序。 冒泡排序 1.对一组数相邻两数依次进行比较,若第一个比第二个大,则交换两数字,否则不交换; 2.依次比较换位到最后一位,则最后一位在一次排序中最大; 3.保持最后一位不动,进行第二次排序,排序完成后,最后两位依次最大; 4.进行第3.4…次排序,直到没有数字需要进行比较排序 代码: 来源: CSDN 作者

排序算法 -- 选择排序(SelectSort)

a 夏天 提交于 2020-03-10 03:56:37
一、选择排序思想 选择排序(select sorting)也是一种简单的排序方法。它的基本思想是:第一次从 arr[0]~arr[n-1] 中选取最小值,与 arr[0]交换,第二次从 arr[1]~arr[n-1]中选取最小值,与 arr[1]交换,第三次从 arr[2]~arr[n-1]中选取最小值,与 arr[2] 交换,…,第 i 次从 arr[i-1]~arr[n-1]中选取最小值,与 arr[i-1]交换,…, 第 n-1 次从 arr[n-2]~arr[n-1]中选取最小值, 与 arr[n-2]交换,总共通过 n-1 次,得到一个按排序码从小到大排列的有序序列。 二、选择排序图示 三、java 编写选择排序代码 package point2 ; import java . util . Arrays ; /** * @description: 选择排序 * @author: hyr * @time: 2020/1/25 19:40 */ public class SelectSort { // 测试 public static void main ( String [ ] args ) { int [ ] arr = { 1 , - 3 , 5 , 6 , 9 , 3 } ; SelectSort . selectSort ( arr ) ; } //

数据结构与算法系列十(排序算法概述)

匆匆过客 提交于 2020-03-08 13:43:47
1.引子 1.1.为什么要学习数据结构与算法? 有人说,数据结构与算法,计算机网络,与操作系统都一样,脱离日常开发,除了面试这辈子可能都用不到呀! 有人说,我是做业务开发的,只要熟练API,熟练框架,熟练各种中间件,写的代码不也能“飞”起来吗? 于是问题来了:为什么还要学习数据结构与算法呢? #理由一: 面试的时候,千万不要被数据结构与算法拖了后腿 #理由二: 你真的愿意做一辈子CRUD Boy吗 #理由三: 不想写出开源框架,中间件的工程师,不是好厨子 1.2.如何系统化学习数据结构与算法? 我想好了,还是需要学习数据结构与算法。但是我有两个困惑: 1.如何着手学习呢? 2.有哪些内容要学习呢? 学习方法推荐: #学习方法 1.从基础开始,系统化学习 2.多动手,每一种数据结构与算法,都自己用代码实现出来 3.思路更重要:理解实现思想,不要背代码 4.与日常开发结合,对应应用场景 学习内容推荐: 数据结构与算法内容比较多,我们本着实用原则,学习经典的、常用的数据结构、与常用算法 #学习内容: 1.数据结构的定义 2.算法的定义 3.复杂度分析 4.常用数据结构 数组、链表、栈、队列 散列表、二叉树、堆 跳表、图 5.常用算法 递归、排序、二分查找 搜索、哈希、贪心、分治 动态规划、字符串匹配 2.考考你 在前面两篇,我们详细看了常用算法的第一个主题:递归

数据结构——复习九(排序)

微笑、不失礼 提交于 2020-03-08 06:37:30
排序 稳定排序和不稳定排序 假设Ri=Rj(0<=i,j<=n-1,i≠j),且在排序前的序列中Ri领先于Rj(即i<j),若在排序后的序列中Ri仍领先于Rj,则称所用的排序方法是稳定的,否则是不稳定的。 内部排序:待排序记录存放在内存 外部排序:排序过程中需对外存进行访问的排序 插入排序:直接插入排序、折半插入排序、希尔排序、表插入排序 交换排序:起泡排序、快速排序 选择排序:简单选择排序、堆排序 归并排序:2-路归并排序 分配排序 插入排序 直接插入排序 上面的过程很直观,挺简单的,对我来说比较好理解 //我自己写了一种,还有一种都是一样的,后面那种对理解shell排序比较有帮助 void straisort ( int r [ ] , int n ) { int i , j , k ; for ( i = 2 ; i <= n ; i ++ ) { r [ 0 ] = r [ i ] ; j = i - 1 ; for ( k = 1 ; k <= j ; k ++ ) { if ( r [ 0 ] < r [ k ] ) r [ k + 1 ] = r [ k ] ; else { r [ k + 1 ] = r [ 0 ] ; break ; } } } } void straisort ( int r [ ] , int n ) { int i , j ; for (

排序算法之二分法(折半)插入排序算法

安稳与你 提交于 2020-03-06 21:45:58
基本思想 折半插入排序的基本思想与直接插入排序一样,在插入第 i ( i ≥ 1 ) 个元素时,前面 i − 1 个元素已经排好序。差别在于寻找插入位置的方法不同。折半插入排序是採用折半查找法来寻找插入位置的。 折半查找法的基本思路是:用待插元素的值与当前查找序列的中间元素的值进行比較,以当前查找序列的中间元素为分界,确定待插元素是在当前查找序列的左边还是右边,假设是在其左边。则以该左边序列为当前查找序列。右边也相似。依照上述方法,递归地处理新序列。直到当前查找序列的长度小于1时查找过程结束。 代码 //待排数据存储在数组a中。以及待排序列的左右边界 public void BinaryInsertSort(int[] a, int left, int right) { int low, middle, high; int temp; for (int i = left + 1; i <= right; i++) { temp = a[i]; low = left; high = i - 1; while (low <= high) { middle = (low + high) / 2; if (a[i] < a[middle]) high = middle - 1; else low = middle + 1; } for (int j = i - 1; j >= low; j

C#各种排序算法代码实现

被刻印的时光 ゝ 提交于 2020-03-06 11:48:49
转自: https://blog.csdn.net/sniper007/article/details/53080131 排序是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为“有序”的记录序列。分内部排序和外部排序。若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问题为外部排序。内部排序的过程是一个逐步扩大记录的有序序列长度的过程。 将杂乱无章的数据元素,通过一定的方法按关键字顺序排列的过程叫做排序。假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的。 分类 稳定排序:假设在待排序的文件中,存在两个或两个以上的记录具有相同的关键字,在用某种排序法排序后,若这些相同关键字的元素的相对次序仍然不变,则这种排序方法是稳定的。其中冒泡,插入,基数,归并属于稳定排序,选择,快速,希尔,堆属于不稳定排序。 就地排序:若排序算法所需的辅助空间并不依赖于问题的规模n,即辅助空间为O(1),则称为就地排序。(百度百科) 冒泡排序 已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先比较a[1