排序算法2
归并排序
主要思想
利用分治策略将数组切分至只剩一个元素,再按顺序合并到辅助数组中,最后将数据复制到待排序的数组即可。
代码
static void MergeSort(int[] arr, int left, int right, int[] temp)
{
if (left < right)
{
int mid = (left + right) / 2; //中间索引
//向左递归分解
MergeSort(arr, left, mid, temp);
//向右递归分解
MergeSort(arr, mid + 1, right, temp);
//合并
Merge(arr, left, mid, right, temp);
}
}
/// <summary>
///
/// </summary>
/// <param name="arr">排序的原始数组</param>
/// <param name="left">左边有序序列的初始索引</param>
/// <param name="mid">左右的分隔索引</param>
/// <param name="right">右边索引</param>
/// <param name="temp">用作中转的数组</param>
static void Merge(int[] arr, int left, int mid, int right, int[] temp)
{
int i = left; //初始化 i,左边有序序列的初始索引
int j = mid + 1; //初始化 j,右边有序序列的初始索引
int t = 0; //初始化t,temp数组的当前索引
//1.
//先把左右两边(有序)的数据按照规则填充到temp数组中
//直到左右两边有序序列有一边处理完毕为止
while (i <= mid && j <= right)
{
//左边小
if (arr[i] <= arr[j])
temp[t++] = arr[i++];
else
temp[t++] = arr[j++];
}
/*2.
* 将有剩余一边的数据依次全部填充到temp中
*/
while (i <= mid)
{
temp[t++] = arr[i++];
}
while (j <= right)
{
temp[t++] = arr[j++];
}
/*3.
* 将temp数组的元素拷贝到arr,并不是每次都拷贝所有
*/
t = 0;
int tempLeft = left;
while (tempLeft <= right)
{
arr[tempLeft++] = temp[t++];
}
}
快速排序
主要思想
是对冒泡排序的一种改进,基本思想是通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的数据比另外一部分的所有数据都小,然后再按此方法对两部分数据分别进行继续拆分,直到每部分仅剩一个数据为止。以此来达到让整个数据变成有序序列的目的
代码
static void QuickSort(int[] arr, int left, int right)
{
int l = left; //左下标
int r = right; //右下标
//pivot 中轴
int pivot = arr[(left + right) / 2];
int temp = 0;
//让比pivot值小的放在左边,比pivot大的放在右边
while (l < r)
{
//在pivot左边找到一个大于或等于pivot的值,才退出
while (arr[l] < pivot)
{
l += 1;
}
//在pivot右边找到一个小于或等于pivot的值,才退出
while (arr[r] > pivot)
{
r--;
}
//如果 l>=r 说明pivot的左右两边的值已经分好了
if (l >= r)
break;
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
//如果交换完后 发现 arr[l] == pivot,把r前移
if (arr[l] == pivot)
r--;
//如果交换完后,发现 arr[r] == pivot, 把l后移
if (arr[r] == pivot)
l++;
}
//如果 l == r,必须l++,r--,否则会栈溢出
if (l == r)
{
l++;
r--;
}
//向左递归
if (left < r)
{
QuickSort(arr, left, r);
}
if (right > l)
{
QuickSort(arr, l, right);
}
}
基数排序
主要思想
将整数按照位数进行切割,放入对应的“桶”中,再顺序取出。
将所有待比较的数值统一为一样的长度,数位短的前面补零,然后从最低位开始,依照每一位的数值大小进行排序,从最低位一直到最高位排序完成后,数列就成了有序序列。
代码
static void RadixSort(int[] arr)
{
#region 最终实现
//得到最大位数
int max = arr[0];
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
int maxLength = (max + "").Length;
for (int i = 0, digit = 1; i < maxLength; i++, digit *= 10)
{
int[,] bucket = new int[10, arr.Length];
//为了记录每个桶中实际存放了多少数据,定义一个一维数组来记录各个桶每次放入的数据个数
int[] bucketElementCnt = new int[10];
for (int j = 0; j < arr.Length; j++)
{
int digitOfElement = arr[j] / digit % 10;
//放入到对应的桶中
bucket[digitOfElement, bucketElementCnt[digitOfElement]++] = arr[j];
}
//取出桶中的数据
int index = 0;
for (int k = 0; k < bucketElementCnt.Length; k++)
{
//如果桶中有数据,才放入到原数组
if (bucketElementCnt[k] != 0)
{
//循环第k个桶
for (int l = 0; l < bucketElementCnt[k]; l++)
{
//取出元素放入arr
arr[index++] = bucket[k, l];
}
}
bucketElementCnt[k] = 0;
}
}
#endregion
#region 思路模拟
/*
//第一轮排序(针对每个元素的个位进行排序)
int[,] bucket = new int[10, arr.Length];
//为了记录每个桶中实际存放了多少数据,定义一个一维数组来记录各个桶每次放入的数据个数
int[] bucketElementCnt = new int[10];
for (int j = 0; j < arr.Length; j++)
{
//取出每个元素的个位
int digitOfElement = arr[j] % 10;
//放入到对应的桶中
bucket[digitOfElement, bucketElementCnt[digitOfElement]++] = arr[j];
}
//取出桶中的数据
int index = 0;
for (int k = 0; k < bucketElementCnt.Length; k++)
{
//如果桶中有数据,才放入到原数组
if (bucketElementCnt[k] != 0)
{
//循环第k个桶
for (int l = 0; l < bucketElementCnt[k]; l++)
{
//取出元素放入arr
arr[index++] = bucket[k, l];
}
}
bucketElementCnt[k] = 0;
}
//第二轮
for (int j = 0; j < arr.Length; j++)
{
//取出每个元素的十位
int digitOfElement = arr[j] / 10 % 10;
//放入到对应的桶中
bucket[digitOfElement, bucketElementCnt[digitOfElement]++] = arr[j];
}
//取出桶中的数据
index = 0;
for (int k = 0; k < bucketElementCnt.Length; k++)
{
//如果桶中有数据,才放入到原数组
if (bucketElementCnt[k] != 0)
{
//循环第k个桶
for (int l = 0; l < bucketElementCnt[k]; l++)
{
//取出元素放入arr
arr[index++] = bucket[k, l];
}
}
bucketElementCnt[k] = 0;
}
//第三轮
for (int j = 0; j < arr.Length; j++)
{
//取出每个元素的百位
int digitOfElement = arr[j] / 100 % 10;
//放入到对应的桶中
bucket[digitOfElement, bucketElementCnt[digitOfElement]++] = arr[j];
}
//取出桶中的数据
index = 0;
for (int k = 0; k < bucketElementCnt.Length; k++)
{
//如果桶中有数据,才放入到原数组
if (bucketElementCnt[k] != 0)
{
//循环第k个桶
for (int l = 0; l < bucketElementCnt[k]; l++)
{
//取出元素放入arr
arr[index++] = bucket[k, l];
}
}
bucketElementCnt[k] = 0;
}
*/
#endregion
}
所有代码
using System;
namespace AllSortingAlgorithms
{
class Program
{
static void Main(string[] args)
{
int[] arr = new int[8000000];
for (int i = 0; i < arr.Length; i++)
{
arr[i] = (new Random()).Next(0, 8000000);
}
Console.WriteLine("排序前: " + DateTime.Now.ToString() + " " + DateTime.Now.Millisecond.ToString());
RadixSort(arr);
Console.WriteLine("排序后: " + DateTime.Now.ToString() + " " + DateTime.Now.Millisecond.ToString());
//foreach (var item in arr)
//{
// Console.Write(item + " ");
//}
//int[] arr = new int[10];
//for (int i = 0; i < arr.Length; i++)
//{
// arr[i] = (new Random()).Next(0, 20);
//}
//RadixSort(arr);
//foreach (var item in arr)
//{
// Console.Write(item + " ");
//}
}
static void BubbleSort(int[] arr)
{
for (int i = 0; i < arr.Length - 1; i++)
{
bool flag = false;
for (int j = 0; j < arr.Length - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
flag = true;
int t = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = t;
}
}
if (!flag)
break;
}
}
static void SelectSort(int[] arr)
{
for (int i = 0; i < arr.Length - 1; i++)
{
int min = arr[i];
int minId = i;
for (int j = i + 1; j < arr.Length; j++)
{
if (min > arr[j])
{
min = arr[j];
minId = j;
}
}
if (minId != i)
{
arr[minId] = arr[i];
arr[i] = min;
}
}
}
static void InsertSort(int[] arr)
{
for (int i = 1; i < arr.Length; i++)
{
int insertVal = arr[i];
int insertId = i - 1;
while (insertId >= 0 && insertVal < arr[insertId])
{
arr[insertId + 1] = arr[insertId];
insertId--;
}
arr[insertId + 1] = insertVal;
}
}
static void ShellSortVersion1(int[] arr)
{
for (int gap = arr.Length / 2; gap > 0; gap /= 2)
{
for (int i = gap; i < arr.Length; i++)
{
for (int j = i - gap; j >= 0; j -= gap)
{
if (arr[j] > arr[j + gap])
{
int t = arr[j];
arr[j] = arr[j + gap];
arr[j + gap] = t;
}
}
}
}
}
static void ShellSortVersion2(int[] arr)
{
for (int gap = arr.Length / 2; gap > 0; gap /= 2)
{
for (int i = gap; i < arr.Length; i++)
{
int id = i;
int t = arr[i];
if (arr[id] < arr[id - gap])
{
while (id - gap >= 0 && t < arr[id - gap])
{
arr[id] = arr[id - gap];
id -= gap;
}
}
arr[id] = t;
}
}
}
static void QuickSort(int[] arr, int left, int right)
{
int l = left;
int r = right;
int pivot = arr[(left + right) / 2];
int temp = 0;
while (l < r)
{
while (arr[l] < pivot)
{
l++;
}
while (arr[r] > pivot)
{
r--;
}
if (l >= r) break;
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
if (arr[l] == pivot)
r--;
if (arr[r] == pivot)
l++;
}
if (l == r)
{
l++;
r--;
}
if (left < r)
{
QuickSort(arr, left, r);
}
if (right > l)
{
QuickSort(arr, l, right);
}
}
static void Merge(int[] arr, int left, int mid, int right, int[] temp)
{
int i = left;
int j = mid + 1;
int t = 0;
while (i <= mid && j <= right)
{
if (arr[i] <= arr[j])
temp[t++] = arr[i++];
else
temp[t++] = arr[j++];
}
while (i <= mid)
{
temp[t++] = arr[i++];
}
while (j <= right)
{
temp[t++] = arr[j++];
}
t = 0;
int tempLeft = left;
while (tempLeft <= right)
{
arr[tempLeft++] = temp[t++];
}
}
static void MergeSort(int[] arr, int left, int right, int[] temp)
{
if (left < right)
{
int mid = (left + right) / 2;
MergeSort(arr, left, mid, temp);
MergeSort(arr, mid + 1, right, temp);
Merge(arr, left, mid, right, temp);
}
}
static void RadixSort(int[] arr)
{
int max = arr[0];
for (int i = 1; i < arr.Length; i++)
{
if (max < arr[i])
max = arr[i];
}
int maxLength = (max + "").Length;
for (int i = 0, digit = 1; i < maxLength; i++, digit *= 10)
{
int[,] bucket = new int[10, arr.Length];
int[] bucketElementCnt = new int[10];
for (int j = 0; j < arr.Length; j++)
{
int digitOfElement = arr[j] / digit % 10;
bucket[digitOfElement, bucketElementCnt[digitOfElement]++] = arr[j];
}
int index = 0;
for (int j = 0; j < bucketElementCnt.Length; j++)
{
if (bucketElementCnt[j] != 0)
{
for (int k = 0; k < bucketElementCnt[j]; k++)
{
arr[index++] = bucket[j, k];
}
}
bucketElementCnt[j] = 0;
}
}
}
}
}