排序是将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列。排序根据涉及的存储器的不同分为内部排序和外部排序。
内部排序是指待排序记录存放在内存进行的排序过程;外部排序是指待排序记录的数量很大,以致内存一次不能容纳全部记录,在排序过程中尚需对外存进行访问的排序过程。本文仅讨论内部排序。
1 直接插入排序
最简单的排序方法,基本操作是将一个记录插入到已排好序的有序表中,从而得到一个新的、记录数增1的有序表。
此处为了程序的通用,没有采取数组0位作为哨兵位的做法。
C#实现:
1 | public static int[] StraightInsertionSort(int[] arr) |
2 希尔排序
又称“缩小增量排序”,也是一种属插入排序类的方法,但在时间效率上较直接插入排序有较大的改进。
基本思想是先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
C#实现:
1 | public static int[] ShellSort(int[] arr) |
3 冒泡排序
它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
C#实现:
1 | public static int[] BubbleSort(int[] arr) |
4 快速排序
对冒泡排序的一种改进,基本思想是,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短。
C#实现:
1 | public static int[] QuickSort(int[] arr) |
5 简单选择排序
一趟简单排序的操作为:通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录交换。
C#实现:
1 | public static int[] SimpleSelectionSort(int[] arr) |
6 堆排序
堆排序是一种树形选择排序,是对直接选择排序的有效改进。
初始时把要排序的n个数的序列看作是一棵顺序存储的二叉树(一维数组存储二叉树),调整它们的存储序,使之成为一个堆,将堆顶元素输出,得到n 个元素中最小(或最大)的元素,这时堆的根节点的数最小(或者最大)。然后对前面(n-1)个元素重新调整使之成为堆,输出堆顶元素,得到n 个元素中次小(或次大)的元素。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。
C#实现:
1 | private static int heapSize; |
7 归并排序
C#实现:
1 | public static int[] MergeSort(int[] arr) |
8 基数排序
基数排序是借助“分配”和“收集”两种操作对单逻辑关键字进行排序的一种内部排序方法。例如,若关键字是数值,且其值都在0<=k<=999范围内,则可把每一个十进制数字看成一个关键字,即可认为k由3个关键字(kº,k¹,k²)组成,其中kº是百位数,k¹是十位数,k²是个位数。
C#实现:
1 | public static int[] RadixSort(int[] arr) |
总结:各排序算法的稳定性,时间、空间复杂度比较
附:上述代码的调用示例
1 | static void Main(string[] args) |
参考资料:
八大排序算法
数据结构(c语言版)