排序是日常生活中非常普遍的问题,我们每个人都有自己固定的思维模式,而往往这些固定的思维模式都是效率非常低算法,比如选择排序,插入排序和冒泡排序,使我们很容易想到的排序方法(其实我觉得冒泡可能都不会想到)
所以学习别人的高级算法非常有必要,然而真正理解并不是看的懂就行了,也不是写一次代码跑成功就行了,我们需要熟练了知道它算法具体实现的程序中,每一步是在做什么,然后这个算法的时间复杂度、空间复杂度是多少,是否稳定?回答了这些问题,并且时长拿出来写写,最好能够解决一些编程问题,这样就算掌握了。
我的程序中包括了:冒泡排序、插入排序、选择排序、希尔排序、归并排序、计数排序、堆排序和快速排序,并且记录了每个排序算法每次排序后的结果。
using System.Linq;
using static System.Console;
namespace 排序算法总结
{
class Program
{
//冒泡法排序 稳定
static void BubbleSort(int[] arr)
{
for (int i = 0; i < arr.Length-1; i++)
{
for (int j = 0; j < arr.Length - i - 1; j++)
{
if(arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
Print(arr);
}
}
//插入排序 稳定
static void InsertSort(int[] arr)
{
for (int i = 1; i < arr.Length; i++)
{
int temp = arr[i];
int j;
for ( j = i-1 ; j >= 0; j--)
{
if(arr[j] > temp)
{
arr[j + 1] = arr[j];
}
else { break; }
}
arr[j + 1] = temp;
Print(arr);
}
}
//选择排序 不稳定
static void SelectionSort(int[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
int minIndex = i;
int min = arr[i];
for (int j = i+1; j < arr.Length; j++)
{
if(arr[j] < min)
{
min = arr[j];
minIndex = j;
}
}
arr[minIndex] = arr[i];
arr[i] = min;
Print(arr);
}
}
//希尔排序 不稳定
static void ShellSort(int[] arr)
{
int N = arr.Length;
for (int gap = N/2; gap > 0; gap /= 2 )
{
for (int i = gap; i < N; i++)
{
shellsort(arr, gap, i);
}
}
}
static void shellsort(int[] arr,int gap,int i)
{
int temp = arr[i];
int j;
for (j = i -gap; j >= 0; j -= gap)
{
if (arr[j] > temp)
{
arr[j + gap] = arr[j];
}
else
{
break;
}
}
arr[j + gap] = temp;
Print(arr);
}
//归并排序 稳定
//需要O(n)额外空间
static void MergeSort(int[] arr)
{
int[] temp = new int[arr.Length];
mergesort(arr, 0, arr.Length - 1, temp);
}
static void mergesort(int[] arr,int min ,int max,int[] temp)
{
if(min < max)
{
int mid = (min + max) / 2;
mergesort(arr, min, mid, temp);
mergesort(arr, mid + 1, max, temp);
merge(arr, min, mid, max, temp);
}
Print(arr);
}
static void merge(int[] arr ,int min ,int mid ,int max,int[] temp)
{
int i = min;
int j = mid + 1;
int k = 0;
while(i<= mid && j<= max)
{
if(arr[i] < arr[j])
{
temp[k++] = arr[i++];
}
else
{
temp[k++] = arr[j++];
}
}
while (i <= mid)
{
temp[k++] = arr[i++];
}
while (j <= max)
{
temp[k++] = arr[j++];
}
for (int m = 0; m < k; m++)
{
arr[min + m] = temp[m];
}
}
//计数排序(桶排序,哈希排序)
//两两比较的排序算法时间复杂度极限为O(nlogn)
//计数排序为O(n)
static int[] CountingSort(int[] arr)
{
int k;
bool IsMinLessThan0 = false;
if (arr.Min() < 0)
{
k = arr.Max() - arr.Min() + 1;
IsMinLessThan0 = true;
}
else
{
k = arr.Max() + 1;
IsMinLessThan0 = false;
}
int[] output = new int[arr.Length];
int[] temp = new int[k];
for (int i = 0; i < arr.Length; i++)
{
temp[arr[i]]++;
}
for (int i = 1; i < k; i++)
{
temp[i] += temp[i - 1];
}
for (int i = arr.Length-1; i >0; i--)
{
int a = arr[i];
if (IsMinLessThan0)
{
output[temp[a] - 1] = a + arr.Min(); ;
}
else
{
output[temp[a] - 1] = a;
}
temp[a]--;
}
return output;
}
//快速排序 不稳定
static void QuickSort(int[] arr)
{
quicksort( arr,0,arr.Length-1);
}
static void quicksort(int[] arr,int left,int right)
{
if (left < right)
{
int mid = arr[(left + right) / 2];
int i = left - 1;
int j = right + 1;
while (true)
{
while (arr[++i] < mid) ;
while (arr[--j] > mid) ;
if (i >= j)
{
break;
}
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
Print(arr);
}
quicksort(arr, left, i - 1);
quicksort(arr, j + 1, right);
}
}
//堆排序 不稳定
static void HeapSort(int[] arr)
{
//初始化堆,O(n)
for (int i = arr.Length/2-1; i >=0; i--)
{
AdjustHeap(arr, i, arr.Length - 1);
}
//n次交换位置并调整堆,每次调整堆O(logn)
for (int i = arr.Length-1; i >0; i--)
{
var temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
Print(arr);
AdjustHeap(arr, 0, i - 1);
}
//总的时间复杂度是O(n)+O(nlogn)也就是O(nlogn)
}
static void AdjustHeap(int[] arr,int m ,int n)
{
var t = arr[m];
for (int i = 2*m+1; i <= n; i = 2*i+1)
{
if( i arr[i])
{
i++;
}
if(t >= arr[i])
{
break;
}
arr[m] = arr[i];
m = i;
}
arr[m] = t;
}
//初始化数组
static int[] Init()
{
int[] arr = { 7,1,5,2,4,9,8};
return arr;
}
//打印数组每次输出的值
static void Print(int[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
Write(arr[i] + " ");
}
WriteLine();
}
static void Main(string[] args)
{
int[] arr;
arr = Init();
WriteLine("冒泡法排序");
BubbleSort(arr);
WriteLine();
arr = Init();
WriteLine("选择排序");
SelectionSort(arr);
WriteLine();
arr = Init();
WriteLine("插入排序");
InsertSort(arr);
WriteLine();
arr = Init();
WriteLine("希尔排序");
ShellSort(arr);
WriteLine();
arr = Init();
WriteLine("归并排序");
MergeSort(arr);
WriteLine();
arr = Init();
WriteLine("堆排序");
HeapSort(arr);
WriteLine();
arr = Init();
WriteLine("快速排序");
QuickSort(arr);
WriteLine();
}
}
}
直接复制到IDE中即可运行,下面是运行结果:
冒泡法排序
1 5 2 4 7 8 9
1 2 4 5 7 8 9
1 2 4 5 7 8 9
1 2 4 5 7 8 9
1 2 4 5 7 8 9
1 2 4 5 7 8 9
选择排序
1 7 5 2 4 9 8
1 2 5 7 4 9 8
1 2 4 7 5 9 8
1 2 4 5 7 9 8
1 2 4 5 7 9 8
1 2 4 5 7 8 9
1 2 4 5 7 8 9
插入排序
1 7 5 2 4 9 8
1 5 7 2 4 9 8
1 2 5 7 4 9 8
1 2 4 5 7 9 8
1 2 4 5 7 9 8
1 2 4 5 7 8 9
希尔排序
2 1 5 7 4 9 8
2 1 5 7 4 9 8
2 1 5 7 4 9 8
2 1 5 7 4 9 8
1 2 5 7 4 9 8
1 2 5 7 4 9 8
1 2 5 7 4 9 8
1 2 4 5 7 9 8
1 2 4 5 7 9 8
1 2 4 5 7 8 9
归并排序
7 1 5 2 4 9 8
7 1 5 2 4 9 8
1 7 5 2 4 9 8
1 7 5 2 4 9 8
1 7 5 2 4 9 8
1 7 2 5 4 9 8
1 2 5 7 4 9 8
1 2 5 7 4 9 8
1 2 5 7 4 9 8
1 2 5 7 4 9 8
1 2 5 7 4 9 8
1 2 5 7 4 8 9
1 2 4 5 7 8 9
堆排序
7 4 8 2 1 5 9
5 4 7 2 1 8 9
1 4 5 2 7 8 9
2 4 1 5 7 8 9
1 2 4 5 7 8 9
1 2 4 5 7 8 9
快速排序
2 1 5 7 4 9 8
1 2 5 7 4 9 8
1 2 4 7 5 9 8
1 2 4 5 7 9 8
1 2 4 5 7 8 9
请按任意键继续. . .