排序算法

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

*爱你&永不变心* 提交于 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由所有元素中最长的一个元素的位数计量) 为什么这样就可以完成排序呢? 以从小到大排序为例 首先当按照最低有效位完成分配和收集后,此时得到的序列,是根据元素最低有效位的值从小到大排列的。 当按照次低有效位进行第二次分配和收集后,得到的序列,是先根据元素的次低有效位的值从小到大排列,然后再根据最低有效位的值从小到大排列。 以此类推

算法——选择排序、插入排序和希尔排序(改进的插入排序)

爷,独闯天下 提交于 2020-03-21 00:44:54
3 月,跳不动了?>>> 选择排序 首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。再次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。如此以往,直到 将整个数组排序。 性能 :算法的时间效率取决于比较的次数。对于长度为N的数组,选择排序需要大约N²/2次比较和N次交换。 特点 :1. 运行时间和输入无关 :比如即使输入一个有序的数列,还是会和随机数列一样,进行比较、交换处理。 2. 数据移动是最少的 :共N次交换,即交换次数和数组大小是线性关系。其他任何算法都不具备这个特征,大部分都是线性对数或是平方级别的。 函数实现如下: public class Selection { public static void sort(Comparable[] a) { //将a[]按升序排列 int N=a.length; for(int i=0;i<N;i++) { int min=i; for(int j=i+1;j<N;j++) { if(less(a[j],a[min]))min=j; } exch(a,i,min); } } } 插入排序 就像通常人们整理桥牌的方法一样,一张一张来,将每一张牌插入到其他已经有序的牌中的适当的位置。 在计算机中的实现中,为了给要插入的元素腾出空间

JS--排序算法之简单排序

故事扮演 提交于 2020-03-20 23:27:10
目录 JS排序之简单排序 冒泡排序 直接插入排序 直接选择排序 JS排序之简单排序 冒泡排序 时间复杂度: O(n^2) 稳定的排序算法 特点: 从后向前找,有序区数字一定全部小于(或大于)无序区数字 性能: 慢 优化: 双向冒泡(鸡尾酒排序) function bubbleSort(ary) { let exchange = 0, temp = null, n = ary.length; // i<n-1 而不是 i<n, 当遍历到n-1次时已近排好序了 >, for(let i=0; i<n-1; i++) { // 从后面向前遍历, 用前一项比后一项 for(let j = n-2; j>=i; j--) { if(ary[j+1] < ary[j]) { temp = ary[j]; ary[j] = ary[j+1]; ary[j+1] = temp; exchange = 1; } } // 如果没有发生交换(表明排序完成),直接退出排序 if(exchange) break; } return ary; } 效果示例: 直接插入排序 时间复杂度: O(n^2) 稳定的排序算法 特点: 将单前元素插入前面有序区中排序, 有序区中元素不一定小于(大于)无序区元素 性能: 在数组元素基本有序的情况下速度很快 优化: 设置增量, 让数组基本有序,然后在不断缩减增强(希尔排序)

排序算法之归并排序

大憨熊 提交于 2020-03-20 22:24:19
3 月,跳不动了?>>> 一、分治法的思想 把复杂的问题分解,再分解,成为很小的问题,解决这些小问题之后合并,再合并。这就是分治法的思想。 通常分治法是递归的。 二、归并排序 归并排序就是利用分治法,把无序的数列拆分成多个子数列,子数列再拆分成多个子数列,直至只子数列只有2个数,然后排序,合并,再排序,在合并。。。直到只剩一个有序的数列。 归并排序算法的核心就是:两个各自有序的数列合并成一个完全有序的数列。这个过程可以说很简单,就是从两个数列开头选出最小的数,放入第三个数列中,然后较小的数的指标后移,继续重复操作。直到其中一个数列全部被放入队列中,此时另一个队列剩下的全部数放入第三个数列。 归并排序的时间复杂度是O(nlgn) 如图所示: 三、Java代码实现 public class MergeSort { public static void main(String[] args) { int a[] = {5,3,2,8,7,6,10,20,30,11,22,33,44,100,60,200}; mergeSort(a, 0, a.length - 1); for (int i : a) { System.out.println(i); } } //递归拆分数列 public static void mergeSort(int[] a, int low, int high)

快速排序详解 Java实现

旧街凉风 提交于 2020-03-20 22:10:03
3 月,跳不动了?>>> 一、快速排序的优缺点 对一个东西,首先要讲他的利与弊,才知道怎么使用它。快速排序适用于各种不同的输入数据且在一般应用中比其他排序都要快得多。 快速排序引人注目的特点包括它是原地排序(只需要一个很小的辅助栈),且长度为N的数组排序所需的时间和NlgN成正比 。它的主要缺点是非常脆弱,在实现时要非常小心才能避免低劣的性能。 有了对比,才能知道它的好处。其实快速排序是一种分治的排序算法。它将一个数组分成两个子数组,将两部分独立地排序。讲到这里,有人就会有个疑问,那不是和归并排序一样吗?合并排序也是分治算法的一种,也是将一个数组分成两个子数组。 快速排序和归并排序时互补的:归并排序将数组分成两个子数组分别排序,并将有序的子数组归并以整个数组排序;而快速排序将数组排序的方式则是当两个数组都有序时整个数组也就自然有序了。在第一种情况下,递归调用发生在处理整个数组之前;在第二种情况下,递归调用发生在处理整个数组之后。在归并排序中,一个数组被等分为两半;在快速排序中,切分的位置取决于数组的内容。 这句话最重要。 二、快速排序的实现 public class Quick{ public static void sort(Comparable[] a){ StdRandom.shuffle(a);//消除对输入的依赖,直接生成随机数 sort(a,0,a.length-1);

[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-19 12:41:37
分治法是按照以下方案工作的: 将问题的实例划分为同一个问题的几个较小的实例,最好拥有同样的规模 对这些较小的实例求解(一般使用递归方法,但在问题规模足够小的时候,有时会利用另一种算法以提高效率) 如果必要的话,合并较小问题的解,以得到原始问题的解 分治法的流程: 4.1 合并排序 合并排序是成功应用分治技术的一个完美例子(书上说的)。 对于一个需要排序的数组,合并排序把它一分为二,并对每个子数组递归排序,然后把这两个排好序的子数组合并为一个有序数组。 代码实现: /** * 合并排序 * @author xiaofeig * @since 2015.9.16 * @param array 要排序的数组 * @return 返回排好序的数组 * */ public static int[] mergeSort(int[] array){ if(array.length>1){ int[] subArray1=subArray(array,0,array.length/2); int[] subArray2=subArray(array,array.length/2,array.length); subArray1=mergeSort(subArray1); subArray2=mergeSort(subArray2); return merge(subArray1,subArray2

oracle中rownum小于xxx分页,排序不稳定

浪子不回头ぞ 提交于 2020-03-19 09:23:08
3 月,跳不动了?>>> 相当数量的blog互相参照,提供类似下列的高效率查询sql,单在分页查询中,由于oracle会进行 排序查询算法的优化,造成排序结果不稳定,不应采用下列方法。 SELECT * FROM (SELECT tt.*, ROWNUM AS rowno FROM ( SELECT t.* FROM emp t WHERE hire\_date BETWEEN TO\_DATE ('20060501', 'yyyymmdd') AND TO_DATE ('20060731', 'yyyymmdd') ORDER BY create\_time DESC, emp\_no) tt WHERE ROWNUM <= 20) table_alias WHERE table_alias.rowno >= 10; 原因:优化器采用了“SORT (ORDER BY STOPKEY)”。 “SORT (ORDER BY STOPKEY)”不需要对所有数据进行排序,而是只要找出结果集中的按特定顺序的最前N条记录,一旦找出了这N条记录,就无需再对剩下的数据进行排序,而直接返回结果。 这种算法我们可以视为是“快速排序”算法的变种。快速排序算法的基本思想是:先将数据分2组集合,保证第一集合中的每个数据都大于第二个集合中每个数据,然后再按这个原则对每个集合进行递归分组, 直到集合的单位最小

实验7 文件

点点圈 提交于 2020-03-19 08:11:24
Part1: 验证性实验 验证性实验2: #include <stdio.h> #include <stdlib.h> #define N 10 // 定义一个结构体类型STU typedef struct student { int num; char name[20]; int score; }STU; int main() { STU st, stmax, stmin; int i; FILE *fp; // 以只读文本方式打开文件file1.dat fp = fopen("file1.dat", "r"); if( !fp ) { // 如果打开失败,则输出错误提示信息,然后退出程序 printf("fail to open file1.dat\n"); exit(0); } stmax.score = 0; // 先假定最高分是0,后面如发现比当前最高分还高的分数,就更新最高分 stmin.score = 100; // 先假定最低分是100分,后面如发现比当前最低分更低的分数,就更新最低分 while(!feof(fp)){ fscanf(fp, "%d %s %d", &st.num, st.name, &st.score); // 从fp指定的文件中格式化读取一个学生信息 if(st.score > stmax.score) stmax = st; else if

插入排序和归并排序

眉间皱痕 提交于 2020-03-19 06:57:46
插入排序思想:在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使这n个数也是排好顺序的。如此反复循环,直到全部排好顺序.(当待排序数据全部有序时,时间复杂度为O(N),最坏情况下时间复杂度为O(N*N),与待排序数据的状态有关). public class InsertSort { public static void insertSort(int[] arr) { if(arr == null || arr.length < 2) return ; for(int i = 1; i < arr.length; i++) { for(int j = i -1; j >= 0 && arr[j] > arr[j+1]; j--) swap(arr, j , j+1); } } public static void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } public static void main(String[] args) { int[] arr = new int[] {3,434,24,656,57,54,88,66}; System.out.print("原始数组:"); for(int i = 0; i <