1.前言
排序是数据处理过程中经常使用的一种操作,其主要目的是便于查找。根据排序的方法大致可以分为插入排序、交换排序、选择排序、归并排序以及分配排序。以下内容将对各个排序算法的实现过程进行分析,以及各自的时间复杂度进行比较。
2.插入排序
插入排序的主要思想是:每次将一个待排序的记录按其关键码的大小插入到一个已经排好序的有序队列中,直到全部记录排好序。
2.1 直接插入排序
基本思想:依次将待排序序列中的每一个记录插入到一个已排好序的序列中,直到全部记录都排好序。
其实现过程如下所示:
实现代码如下:

public static void InsertSort(this int[] arry)
{
//直接插入排序是将待比较的数值与它的前一个数值进行比较,所以外层循环是从第二个数值开始的
for (int i = 1; i < arry.Length; i++)
{
//如果当前元素小于其前面的元素
if (arry[i] < arry[i - 1])
{
//用一个变量来保存当前待比较的数值,因为当一趟比较完成时,我们要将待比较数值置入比它小的数值的后一位
int temp = arry[i];
int j = 0;
for (j = i - 1; j >= 0 && temp < arry[j]; j--)
{
arry[j + 1] = arry[j];
}
arry[j + 1] = temp;
}
}
}
2.2 希尔排序
基本思想:先将整个待排序记录序列分割成若干个子序列,在子序列内分别进行直接插入排序,待整个序列基本有序时,再对全体记录进行一次直接插入排序。
其实现过程如下所示:
实现代码如下:

public static void ShellSort(this int[] arry)
{
int length = arry.Length;
for (int h = length / 2; h > 0; h = h / 2)
{
//here is insert sort
for (int i = h; i < length; i++)
{
int temp = arry[i];
if (temp < arry[i - h])
{
for (int j = 0; j < i; j += h)
{
if (temp < arry[j])
{
temp = arry[j];
arry[j] = arry[i];
arry[i] = temp;
}
}
}
}
}
}
3.交换排序
交换排序的主要思想是:在待排序序列中选两个记录,将它们的关键码进行比较,如果反序则交换他们的位置。
3.1 冒泡排序
基本思想:两两比较向邻记录的关键码,如果反序则交换,直到没有反序的记录为止。
其实现过程如下所示:
实现代码如下:

public static void BubbleSort(this int[] arry)
{
for (int i = 0; i < arry.Length; i++)
{
for(int j = 0;j<arry.Length-i-1;j++)
{
if(arry[j] > arry[j+1])
{
int temp = arry[j+1];
arry[j + 1] = arry[j];
arry[j] = temp;
}
}
}
}
3.2 快速排序
基本思想:首先选择一个轴值(即比较的基准),将待排序记录划分为独立的两个部分,左侧记录的关键码均小于等于轴值,右侧记录的关键码均大于等于轴值,然后分别对这两部分重复上述过程,直到整个序列有序。
其实现过程如下所示:
实现代码如下:

public static void QuickSort(this int[] arry, int left, int right)
{
//左边索引小于右边,则还未排序完成
if (left < right)
{
//取中间的元素作为比较基准,小于他的往左边移,大于他的往右边移
int middle = arry[(left + right) / 2];
int i = left - 1;
int j = right + 1;
while (true)
{
//移动下标,左边的往右移动,右边的向左移动
while (arry[++i] < middle && i < right) ;
while (arry[--j] > middle && j > 0) ;
if (i >= j)
break;
//交换位置
int number = arry[i];
arry[i] = arry[j];
arry[j] = number;
}
QuickSort(arry, left, i - 1);
QuickSort(arry, j + 1, right);
}
}
4.选择排序
选择排序的主要思想是:每趟排序在当前待排序序列中选出关键码最小的记录,添加到有序序列中。其特点是,记录移动的次数较少。
4.1 简单选择排序
基本思想:第 i 趟排序在待排序序列 r[i]~r[n](1≤i≤n-1)中选取关键码最小的记录,并和第 i 个记录交换作为有序序列的第 i 个记录。
其实现过程如下所示:
实现代码如下:

public static void SimpleSelectSort(this int[] arry)
{
int tmp = 0;
int t = 0;//最小数标记
for (int i = 0; i < arry.Length; i++)
{
t = i;
for (int j = i + 1; j < arry.Length; j++)
{
if (arry[t] > arry[j])
{
t = j;
}
}
tmp = arry[i];
arry[i] = arry[t];
arry[t] = tmp;
}
}
4.2 堆排序
基本思想:
5.归并排序
5.1 二路归并排序
6.分配排序
6.1 桶式排序
6.2 基数排序
演示图来源:一像素 的博客 https://www.cnblogs.com/onepixel/articles/7674659.html