using System;
using System.Linq;
using System.Collections.Generic;

//by Alexander Ezharjan

namespace Sort
{
class Program
{
static void Main(string[] args)
{
int[] myArray = new int[10] { 10, 6, 3, 4, 2, 7, 1, 5, 9, 8 };
// BubbleSort(myArray);
// SelectionSort(myArray);
// InsertionSort(myArray);
// ShellSort(myArray);
// QuickSort(myArray);
// HeapSort(myArray);
// CountSort(myArray);
foreach (int element in myArray)
{
Console.Write("{0} ", element);
}

List<int> myList = new List<int>(10) { 10, 6, 3, 4, 2, 7, 1, 5, 9, 8 };
// List<int> newList = new List<int>(10) { 0 };
// BucketSort(myList, 3, 6);
// newList = RecursiveSort(myList);
RadixSort(myList);
Console.WriteLine("\n");
foreach (int element in myList)
{
Console.Write("{0} ", element);
}
// foreach (int element in newList)
// {
// Console.Write("{0} ", element);
// }
}





static void Swap(ref int x, ref int y)
{
int temp = x;
x = y;
y = temp;
}




///冒泡排序
static void BubbleSort(int[] arr)
{
bool swapped;
for (int i = 0; i < arr.Length; i++)
{
swapped = false;
for (int j = 0; j < arr.Length - 1 - i; j++)
if (arr[j] > arr[j + 1])
{
Swap(ref arr[j], ref arr[j + 1]);
if (!swapped) swapped = true;
}
if (!swapped) return;
}
}




///选择排序
static void SelectionSort(int[] arr)
{
int i, j, min, len = arr.Length;
for (i = 0; i < len - 1; i++)
{
min = i;
for (j = i + 1; j < len; j++)
{
if (arr[min].CompareTo(arr[j]) > 0)
{
min = j;
}
}
Swap(ref arr[min], ref arr[i]);
}
}





///插入排序
static void InsertionSort(int[] arr)
{
for (int i = 1; i < arr.Length; i++)
{
int temp = arr[i];
for (int j = i - 1; j >= 0; j--)
{
if (arr[j] > temp)
{
arr[j + 1] = arr[j];
arr[j] = temp;
}
else
break;
}
}
}





///希尔排序
static void ShellSort(int[] arr)
{
int gap = 1;

while (gap < arr.Length)
{
gap = gap * 3 + 1;
}

while (gap > 0)
{
for (int i = gap; i < arr.Length; i++)
{
int tmp = arr[i];
int j = i - gap;
while (j >= 0 && arr[j] > tmp)
{
arr[j + gap] = arr[j];
j -= gap;
}
arr[j + gap] = tmp;
}
gap /= 3;
}
}



///递归排序
static List<int> RecursiveSort(List<int> list)
{
if (list.Count <= 1)
{
return list;
}

int mid = list.Count / 2;
List<int> left = new List<int>(); // 定义左侧List
List<int> right = new List<int>(); // 定义右侧List
// 以下兩個循環把 lst 分為左右兩個 List
for (int i = 0; i < mid; i++)
{
left.Add(list[i]);
}
for (int j = mid; j < list.Count; j++)
{
right.Add(list[j]);
}
left = RecursiveSort(left);
right = RecursiveSort(right);
return MergeSortedList(left, right);
}
/// <summary>
/// 合併兩個已經排好序的List
/// </summary>
/// <param name="left">左側List</param>
/// <param name="right">右側List</param>
/// <returns></returns>
static List<int> MergeSortedList(List<int> left, List<int> right)
{
List<int> temp = new List<int>();
while (left.Count > 0 && right.Count > 0)
{
if (left[0] <= right[0])
{
temp.Add(left[0]);
left.RemoveAt(0);
}
else
{
temp.Add(right[0]);
right.RemoveAt(0);
}
}
if (left.Count > 0)
{
for (int i = 0; i < left.Count; i++)
{
temp.Add(left[i]);
}
}
if (right.Count > 0)
{
for (int i = 0; i < right.Count; i++)
{
temp.Add(right[i]);
}
}
return temp;
}




///快速排序(目标数组,数组的起始位置,数组的终止位置)
static void QuickSort(int[] arr, int left = 0, int right = -1)
{

if (right.Equals(-1)) right = arr.Length - 1;

try
{
int keyValuePosition; //记录关键值的下标

//当传递的目标数组含有两个以上的元素时,进行递归调用。(即:当传递的目标数组只含有一个元素时,此趟排序结束)
if (left < right)
{
keyValuePosition = Partion(arr, left, right); //获取关键值的下标(快排的核心)

QuickSort(arr, left, keyValuePosition - 1); //递归调用,快排划分出来的左区间
QuickSort(arr, keyValuePosition + 1, right); //递归调用,快排划分出来的右区间
}
}
catch (Exception ex)
{
Console.WriteLine("Exception: {0}", ex);
}
}

///快速排序的核心部分:确定关键值在数组中的位置,以此将数组划分成左右两区间,关键值游离在外。(返回关键值应在数组中的下标)
static int Partion(int[] arr, int left, int right)
{
int leftIndex = left; //记录目标数组的起始位置(后续动态的左侧下标)
int rightIndex = right; //记录目标数组的结束位置(后续动态的右侧下标)

int keyValue = arr[left]; //数组的第一个元素作为关键值
int temp;

//当 (左侧动态下标 == 右侧动态下标) 时跳出循环
while (leftIndex < rightIndex)
{
while (leftIndex < rightIndex && arr[leftIndex] <= keyValue) //左侧动态下标逐渐增加,直至找到大于keyValue的下标
{
leftIndex++;
}
while (leftIndex < rightIndex && arr[rightIndex] > keyValue) //右侧动态下标逐渐减小,直至找到小于或等于keyValue的下标
{
rightIndex--;
}
if (leftIndex < rightIndex) //如果leftIndex < rightIndex,则交换左右动态下标所指定的值;当leftIndex==rightIndex时,跳出整个循环
{
temp = arr[leftIndex];
arr[leftIndex] = arr[rightIndex];
arr[rightIndex] = temp;
}
}

//当左右两个动态下标相等时(即:左右下标指向同一个位置),此时便可以确定keyValue的准确位置
temp = keyValue;
if (temp < arr[rightIndex]) //当keyValue < 左右下标同时指向的值,将keyValue与rightIndex - 1指向的值交换,并返回rightIndex - 1
{
arr[left] = arr[rightIndex - 1];
arr[rightIndex - 1] = temp;
return rightIndex - 1;
}
else //当keyValue >= 左右下标同时指向的值,将keyValue与rightIndex指向的值交换,并返回rightIndex
{
arr[left] = arr[rightIndex];
arr[rightIndex] = temp;
return rightIndex;
}
}






/// <summary>
/// 堆排序
/// </summary>
/// <param name="arr">待排序数组</param>
static void HeapSort(int[] arr)
{
int nodeCount = arr.Length;
int[] tempKey = new int[nodeCount + 1];
// 元素索引从1开始
for (int i = 0; i < nodeCount; i++)
{
tempKey[i + 1] = arr[i];
}

// 初始数据建堆(从含最后一个结点的子树开始构建,依次向前,形成整个二叉堆)
for (int i = nodeCount / 2; i >= 1; i--)
{
Restore(tempKey, i, nodeCount);
}

// 不断输出堆顶元素、重构堆,进行排序
for (int i = nodeCount; i > 1; i--)
{
int temp = tempKey[i];
tempKey[i] = tempKey[1];
tempKey[1] = temp;
Restore(tempKey, 1, i - 1);
}

//排序结果
for (int i = 0; i < nodeCount; i++)
{
arr[i] = tempKey[i + 1];
}
}

/// <summary>
/// 二叉堆的重构(针对于已构建好的二叉堆首尾互换之后的重构)
/// </summary>
/// <param name="arr"></param>
/// <param name="rootNode">根结点j</param>
/// <param name="nodeCount">结点数</param>
static void Restore(int[] arr, int rootNode, int nodeCount)
{
while (rootNode <= nodeCount / 2) // 保证根结点有子树
{
//找出左右儿子的最大值
int m = (2 * rootNode + 1 <= nodeCount && arr[2 * rootNode + 1] > arr[2 * rootNode]) ? 2 * rootNode + 1 : 2 * rootNode;

if (arr[m] > arr[rootNode])
{
int temp = arr[m];
arr[m] = arr[rootNode];
arr[rootNode] = temp;
rootNode = m;
}
else
{
break;
}
}
}


///计数排序
static void CountSort(int[] arr)
{
if (arr.Length == 0) return;

int min = arr[0];
int max = min;

foreach (int number in arr)
{
if (number > max)
{
max = number;
}
else if (number < min)
{
min = number;
}
}

int[] counting = new int[max - min + 1];

for (int i = 0; i < arr.Length; i++)
{
counting[arr[i] - min] += 1;
}

int index = -1;
for (int i = 0; i < counting.Length; i++)
{
for (int j = 0; j < counting[i]; j++)
{
index++;
arr[index] = i + min;
}
}
}




///桶排序
static void BucketSort(List<int> list, int bucketCount, int maxBucketCount)
{
List<List<int>> buckets = new List<List<int>>(bucketCount);//二维列表
for (int i = 0; i < bucketCount; i++)
{
buckets.Add(new List<int>());
}
for (int i = 0; i < list.Count; i++)
{
// int j = Mathf.Min(list[i] / (maxBucketCount / bucketCount), bucketCount - 1);//j表示改放的哪个桶,不能大于n-1
int j = Math.Min(list[i] / (maxBucketCount / bucketCount), bucketCount - 1);//j表示改放的哪个桶,不能大于n-1
buckets[j].Add(list[i]);//放入对应桶
for (int x = buckets[j].Count - 1; x > 0; x--)//放一个排序一次,两两对比就可以
{
if (buckets[j][x] < buckets[j][x - 1])//升序
{
int tmp = buckets[j][x];//交换
buckets[j][x] = buckets[j][x - 1];
buckets[j][x - 1] = tmp;
}
else
{
break;//如果不发生交换直接退出,因为前面的之前就排序好了
}
}
}
list.Clear();//输出
for (int i = 0; i < buckets.Count; i++)
{
list.AddRange(buckets[i]);
}
}


///基数排序
static void RadixSort(List<int> list)
{
int maxValue = list.Max();//列表内部方法拿过来用用(在Linq中)
int it = 0;//需要几趟
//maxvalue 9-1 99-2 999-3
//10^0<=9 10^1>9 it=1
//10^0<99 10^1<99 10^2>99 it=2
while (Math.Pow(10, it) <= maxValue)
{
List<List<int>> buckets = new List<List<int>>(10);//分10个桶对应0-9
for (int i = 0; i < 10; i++)
{
buckets.Add(new List<int>());
}//列表初始化大小
for (int i = 0; i < list.Count; i++)//入桶
{
//989 it=0 989/10^it=989 989%10=9;
int digit = (int)((list[i]) / (Math.Pow(10, it)) % 10);//得到对应桶
buckets[digit].Add(list[i]);
}//全部入桶
list.Clear();//依次取出来
for (int i = 0; i < buckets.Count; i++)
{
list.AddRange(buckets[i]);
}
it += 1;//继续下一次循环入桶出桶
}
}
}
}

​参考链接​



作者:艾孜尔江