首先,一张图看懂8中排序之间的关系:

平均速度最快:快速排序

所需辅助空间最多:归并排序

所需辅助空间最少:堆排序

不稳定:快速排序,希尔排序,堆排序。

1. 直接插入排序

基本思想:在要排序的一组数中,假设前面(n-1)[n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

  1. for (int i = ; i < array.Length; i++)
  2. {
  3. if (array[i] > array[i - ])
  4. {
  5. int tmp = array[i];
  6. int j = ;
  7. for (j = i - ; j >= && tmp >array[j]; --j)
  8. {
  9. array[j + ] = array[j];
  10. }
  11. array[j + ] = tmp;
  12. }
  13. }

2.希尔排序(最小增量排序)

基本思想:算法先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。当增量减到1时,进行直接插入排序后,排序完成。

  1. int length = array.Length;
  2. for (int h = length / ; h > ; h = h / )
  3. {
  4. for (int i = h; i < length; i++)
  5. {
  6. T temp = array[i];
  7. if (temp.CompareTo(array[i -h]) < )
  8. {
  9. for (int j = ; j < i; j += h)
  10. {
  11. if (temp.CompareTo(array[j]) < )
  12. {
  13. temp = array[j];
  14. array[j] = array[i];
  15. array[i] = temp;
  16. }
  17. }
  18. }
  19. }
  20. }

3. 简单选择排序

基本思想:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

  1. for (int i = ; i < data.Length-; i++)
  2. {
  3. int min = data[i];
  4. int minIndex = i;
  5. for (int j = i+; j < data.Length; j++)
  6. {
  7. if (data[j] <min)
  8. {
  9. min = data[j];
  10. minIndex = j;
  11. }
  12. }
  13. if (minIndex != i)
  14. {
  15. int temp = data[i];
  16. data[i] = data[minIndex];
  17. data[minIndex] = temp;
  18. }
  19. }

4.  堆排序

基本思想:堆排序是一种树形选择排序,是对直接选择排序的有效改进。堆的定义如下:具有n个元素的序列(h1,h2,...,hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,...,n/2)时称之为堆。在这里只讨论满足前者条件的堆。由堆的定义可以看出,堆顶元素(即第一个元素)必为最大项(大顶堆)。完全二叉树可以很直观地表示堆的结构。堆顶为根,其它为左子树、右子树。初始时把要排序的数的序列看作是一棵顺序存储的二叉树,调整它们的存储序,使之成为一个堆,这时堆的根节点的数最大。然后将根节点与堆的最后一个节点交换。然后对前面(n-1)个数重新调整使之成为堆。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。从算法描述来看,堆排序需要两个过程,一是建立堆,二是堆顶与堆的最后一个元素交换位置。所以堆排序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数实现排序的函数。

  1. static void HeapAdjust(List<int> list,int parent,int length)
  2. {
  3. int temp=list[parent];//parent是索引
  4. int child = * parent + ;
  5. while (child < length)
  6. {
  7. if (child + < length && list[child] < list[child + ]) child++;
  8. if (temp >= list[child])
  9. break;
  10. list[parent] = list[child];
  11. parent = child;
  12. child = * parent + ;
  13. }
  14. list[parent] = temp;
  15. }
  16. public static List<int> HeapSort(List<int> list, int top)
  17. {
  18. List<int> topNode = new List<int>();
  19. for (int i = list.Count / - ; i >= ; i--)
  20. {
  21. HeapAdjust(list, i, list.Count);//最大堆
  22. }
  23. for (int i = list.Count - ; i >= list.Count - top; i--)
  24. {
  25. int temp = list[];
  26. list[] = list[i];
  27. list[i] = temp;
  28. topNode.Add(temp);
  29. HeapAdjust(list, , i);
  30. }
  31. return topNode;
  32. }

5.冒泡排序

基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。

  1. int[] numbers = { , , , , , , , , , }; //定义一个要排序的数组,这里可以随便写多少个数
  2. for (int i = ; i < numbers.Length - ; i++) //外层 循环比较遍数
  3. {
  4. for (int j = ; j < numbers.Length - - i; j++)
  5. {
  6. if (numbers[j] > numbers[j + ]) //两个数进行比较,如果大于就交换
  7. {
  8. int temp = numbers[j]; //temp 两个数交换时要有第三个数来过度
  9. numbers[j] = numbers[j + ];
  10. numbers[j + ] = temp;
  11. }
  12. }
  13. }

6.快速排序

基本思想:选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。

  1. private static int QuickSort_Once(int[] _pnArray, int _pnLow, int _pnHigh)
  2. {
  3. int nPivot = _pnArray[_pnLow];
  4. int i = _pnLow, j = _pnHigh;
  5. while (i < j)
  6. {
  7. while (_pnArray[j] >= nPivot && i<j) j--;
  8. _pnArray[i] = _pnArray[j];
  9. while (_pnArray[i] <= nPivot && i<j) i++;
  10. _pnArray[j] = _pnArray[i];
  11. }
  12. _pnArray[i] = nPivot;
  13. return i;
  14. }
  15. private static void QuickSort(int[] _pnArray, int _pnLow, int _pnHigh)
  16. {
  17. if (_pnLow >= _pnHigh) return;
  18. int _nPivotIndex = QuickSort_Once(_pnArray, _pnLow, _pnHigh);
  19. QuickSort(_pnArray, _pnLow, _nPivotIndex-);
  20. QuickSort(_pnArray, _nPivotIndex + ,_pnHigh);
  21. }

7.归并排序

基本思想:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

  1. //归并排序(目标数组,子表的起始位置,子表的终止位置)
  2. private static void MergeSortFunction(int[] array, int first, int last)
  3. {
  4. try
  5. {
  6. if (first < last) //子表的长度大于1,则进入下面的递归处理
  7. {
  8. int mid = (first + last) / ; //子表划分的位置
  9. MergeSortFunction(array, first, mid); //对划分出来的左侧子表进行递归划分
  10. MergeSortFunction(array, mid + , last); //对划分出来的右侧子表进行递归划分
  11. MergeSortCore(array, first, mid, last); //对左右子表进行有序的整合(归并排序的核心部分)
  12. }
  13. }
  14. catch (Exception ex)
  15. { }
  16. }
  17. //归并排序的核心部分:将两个有序的左右子表(以mid区分),合并成一个有序的表
  18. private static void MergeSortCore(int[] array, int first, int mid, int last)
  19. {
  20. try
  21. {
  22. int indexA = first; //左侧子表的起始位置
  23. int indexB = mid + ; //右侧子表的起始位置
  24. int[] temp = new int[last + ]; //声明数组(暂存左右子表的所有有序数列):长度等于左右子表的长度之和。
  25. int tempIndex = ;
  26. while (indexA <= mid && indexB <= last) //进行左右子表的遍历,如果其中有一个子表遍历完,则跳出循环
  27. {
  28. if (array[indexA] <= array[indexB]) //此时左子表的数 <= 右子表的数
  29. {
  30. temp[tempIndex++] = array[indexA++]; //将左子表的数放入暂存数组中,遍历左子表下标++
  31. }
  32. else//此时左子表的数 > 右子表的数
  33. {
  34. temp[tempIndex++] = array[indexB++]; //将右子表的数放入暂存数组中,遍历右子表下标++
  35. }
  36. }
  37. //有一侧子表遍历完后,跳出循环,将另外一侧子表剩下的数一次放入暂存数组中(有序)
  38. while (indexA <= mid)
  39. {
  40. temp[tempIndex++] = array[indexA++];
  41. }
  42. while (indexB <= last)
  43. {
  44. temp[tempIndex++] = array[indexB++];
  45. }
  46. //将暂存数组中有序的数列写入目标数组的制定位置,使进行归并的数组段有序
  47. tempIndex = ;
  48. for (int i = first; i <= last; i++)
  49. {
  50. array[i] = temp[tempIndex++];
  51. }
  52. }
  53. catch (Exception ex)
  54. { }
  55. }

8.基数排序

基本思想:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。

  1. public static int[] RadixSort(int[] ArrayToSort, int digit)
  2. {
  3. //low to high digit
  4. for (int k = ; k <= digit; k++)
  5. {
  6. //temp array to store the sort result inside digit
  7. int[] tmpArray = new int[ArrayToSort.Length];
  8.  
  9. //temp array for countingsort
  10. int[] tmpCountingSortArray = new int[]{,,,,,,,,,};
  11.  
  12. //CountingSort
  13. for (int i = ; i < ArrayToSort.Length; i++)
  14. {
  15. //split the specified digit from the element
  16. int tmpSplitDigit = ArrayToSort[i]/(int)Math.Pow(,k-) - (ArrayToSort[i]/(int)Math.Pow(,k))*;
  17. tmpCountingSortArray[tmpSplitDigit] += ;
  18. }
  19.  
  20. for (int m = ; m < ; m++)
  21. {
  22. tmpCountingSortArray[m] += tmpCountingSortArray[m - ];
  23. }
  24.  
  25. //output the value to result
  26. for (int n = ArrayToSort.Length - ; n >= ; n--)
  27. {
  28. int tmpSplitDigit = ArrayToSort[n] / (int)Math.Pow(,k - ) - (ArrayToSort[n]/(int)Math.Pow(,k)) * ;
  29. tmpArray[tmpCountingSortArray[tmpSplitDigit]-] = ArrayToSort[n];
  30. tmpCountingSortArray[tmpSplitDigit] -= ;
  31. }
  32.  
  33. //copy the digit-inside sort result to source array
  34. for (int p = ; p < ArrayToSort.Length; p++)
  35. {
  36. ArrayToSort[p] = tmpArray[p];
  37. }
  38. }
  39.  
  40. return ArrayToSort;
  41. }

C# 笔记——排序的更多相关文章

  1. [笔记]ACM笔记 - 排序小技巧

    Description 一个数组,要求先对前n个数字排序(以方便后续操作):又要求对前n+i个数字排序:又要求对前n+j - 前n+k个数字排序(i.j.k的大小远小于n,且i.j.k间没有大小关系) ...

  2. Java学习笔记——排序算法之快速排序

    会当凌绝顶,一览众山小. --望岳 如果说有哪个排序算法不能不会,那就是快速排序(Quick Sort)了 快速排序简单而高效,是最适合学习的进阶排序算法. 直接上代码: public class Q ...

  3. Java学习笔记——排序算法之进阶排序(堆排序与分治并归排序)

    春蚕到死丝方尽,蜡炬成灰泪始干 --无题 这里介绍两个比较难的算法: 1.堆排序 2.分治并归排序 先说堆. 这里请大家先自行了解完全二叉树的数据结构. 堆是完全二叉树.大顶堆是在堆中,任意双亲值都大 ...

  4. Java学习笔记——排序算法之希尔排序(Shell Sort)

    落日楼头,断鸿声里,江南游子.把吴钩看了,栏杆拍遍,无人会,登临意. --水龙吟·登建康赏心亭 希尔算法是希尔(D.L.Shell)于1959年提出的一种排序算法.是第一个时间复杂度突破O(n²)的算 ...

  5. Java学习笔记——排序算法之简单排序

    男儿何不带吴钩,收取关山五十州.请君暂上凌烟阁,若个书生万户侯? --南园十三首 三种排序法: 1.冒泡法 2.简单选择法 3.直接插入法   上代码: 1.冒泡排序 public class Bub ...

  6. STL学习笔记--排序算法

    排序算法 C++ STL 的排序算法(Sorting algorithms)是一组将无序序列排列成有序序列的模板函数或与排序相关的模板函数,提供了排序.折半搜索.归并.集合操作.堆操作.最值求解.字典 ...

  7. DataTable学习笔记---排序细则、列隐藏

    耽误了好几天,因为要做一个嵌入式的实验-android内核编译与裁剪,很久之前装的wubi不知道为什么运行出错了,然后看着当前的win7系统觉得有点讨厌了,也是因为快1年半没装机了,所以就重新装机了, ...

  8. C++面试笔记--排序

    这里我们开始复习排序的一些面试题. 首先我们来看一下各个排序方法的时间复杂度和稳定性的比较,见下面表格: 排序法 平均时间 最差情形 稳定度 额外空间 备注 冒泡 O(n2)     O(n2) 稳定 ...

  9. Java基础 TreeSet()来实现数组的【定制排序】 : Comparable接口(自然排序) 或者 Comparator接口 (定制排序)

    笔记: //排序真麻烦!没有C++里的好用又方便!ORZ!ORZ!数组排序还还自己写个TreeSet()和( Comparable接口(自然排序) 或者 Comparator接口 (定制排序))imp ...

随机推荐

  1. 源码安装和yum安装的区别。

    yum是将yum源中别人已经编译好的rpm包下载到本地,然后安装,不需要考虑依赖,主要是方便.源码安装没法人为的控制,安装的版本也很低. 源码安装需要自己编译,安装,编译过程中可以设置参数.可安装的版 ...

  2. IDEA中使用Docker: 图形化 or 命令行 ,你更稀罕那个??

    Docker简介: Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化. 容器是完全使用沙箱机 ...

  3. bzoj1483: [HNOI2009]梦幻布丁(链表+启发式合并)

    题目大意:一个序列,两种操作. ①把其中的一种数修改成另一种数 ②询问有多少段不同的数如1 2 2 1为3段(1 / 2 2 / 1). 昨晚的BC的C题和这题很类似,于是现学现写居然过了十分开心. ...

  4. mybatis 根据id批量删除的两种方法

    原文:https://blog.csdn.net/qq_40010745/article/details/81032218 mybatis 根据id批量删除的两种方法   第一种,直接传递给mappe ...

  5. 【转载】Innodb共享表空间VS独立表空间

    http://www.mysqlsupport.cn/innodb%E5%85%B1%E4%BA%AB%E8%A1%A8%E7%A9%BA%E9%97%B4vs%E7%8B%AC%E7%AB%8B%E ...

  6. 基于Bootstrap的遮罩层,带有加载提示

    1.body中的html <div class="modal fade" id="loadingModal"> <div style=&quo ...

  7. C语言双链表遍历,插入,删除

    #include<stdio.h> #include<stdlib.h> #include <string.h> #define bzero(a, b) memse ...

  8. JQuery源码实现

    技术提高篇--- 推荐--- 动脑学院--- http://www.toutiao.com/a6368703139592569089/

  9. php环境的安装

    一.xampp的安装 1.下载xampp安装包. 2.next下一步傻瓜式的安装. 3.输入地址127.0.0.1进入如下页面. 二.LAMP环境的安装

  10. LightOJ 1137 - Expanding Rods 基础计算几何

    http://www.lightoj.com/volume_showproblem.php?problem=1137 题意:一根长度为L的杆热膨胀为L',左端点到右端点间距离不变,且膨胀后的杆的弧为圆 ...