大家好,这是自己整理的C#常见排序算法笔记,方便自己学习的同时分享出来,感谢支持。
public class Solution
{
// 冒泡排序
static void bubbleSort(int[] nums)
{
int n = nums.Length; // 得到数组的长度
for (int i = 0; i < n; i++)
{
bool flag = false; // 表示本轮是否有进行变量交换
for (int idx = 0; idx < n - i - 1; idx++)
{
if (nums[idx] > nums[idx + 1])
{
int temp = nums[idx];
nums[idx] = nums[idx + 1];
nums[idx + 1] = temp;
flag = true;
}
}
// 如果flag为False,那说明本轮排序没有进行任何变量交换
// 数组已经是有序的了
if (!flag)
{
break;
}
}
}
static void Main()
{
int[] test = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
bubbleSort(test);
foreach (int item in test)
{
Console.WriteLine(item);
}
}
}
public class Solution
{
// 选择排序
public static void selectionSort(int[] nums)
{
int n = nums.Length;
for (int i = 0; i < n; i++)
{
// 找无序区中最小的元素
int minIndex = i; //无序区中的最小元素的索引
for (int j = i + 1; j < n; j++)
{
if (nums[j] < nums[minIndex])
{
minIndex = j;
}
}
// 执行完上面的循环后
// minIndex就是无序区中的最小元素的索引
// 把最小元素和有序区的后一个元素交换位置
int temp = nums[i];
nums[i] = nums[minIndex];
nums[minIndex] = temp;
}
}
static void Main()
{
int[] test = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
selectionSort(test);
foreach (int item in test)
{
Console.WriteLine(item);
}
}
}
public class Solution
{
// 插入排序
public static void insertSort(int[] nums)
{
int n = nums.Length; // 数组的长度
for (int i = 0; i < n - 1; i++)
{
int curNum = nums[i + 1]; // 无序区的第一个元素
int idx = i; //有序区的最后一个元素的索引
while (idx >= 0 && nums[idx] > curNum)
{
nums[idx + 1] = nums[idx]; // 把有序区的元素往后挪一位
idx -= 1;
}
nums[idx + 1] = curNum;
}
}
static void Main()
{
int[] test = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
insertSort(test);
foreach (int item in test)
{
Console.WriteLine(item);
}
}
}
public class Solution
{
// 分区
public static int partition(int[] nums, int left, int right)
{
int pivot = nums[left]; // 区域的第一个元素作为基准值
while (left < right)
{
while (left < right && nums[right] > pivot)
right--;
nums[left] = nums[right];
while (left < right && nums[left] <= pivot)
left++;
nums[right] = nums[left];
}
nums[right] = pivot; // 基准值的正确位置
return left; // 返回基准值
}
// 快速排序
public static void quickSort(int[] nums, int left, int right)
{
if (left >= right)
return;
// 分区 --> 分好区之后的基准值的索引
int pivotIndex = partition(nums, left, right);
// 左边的区域, left -> pivotIndex - 1
quickSort(nums, left, pivotIndex - 1);
// 右边的区域,pivotIndex+1->right
quickSort(nums, pivotIndex + 1, right);
}
static void Main()
{
int[] test = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
quickSort(test, 0, test.Length - 1);
foreach (int item in test)
{
Console.WriteLine(item);
}
}
}
public class Solution
{
// 随机分区
public static int randomPartition(int[] nums, int left, int right)
{
Random random = new Random(); // 随机生成数
int i = random.Next(left,right);
int temp = nums[i];
nums[i] = nums[right];
nums[right] = nums[i];
return partition(nums, left, right);
}
// 分区
public static int partition(int[] nums, int left, int right)
{
int pivot = nums[left]; // 区域的第一个元素作为基准值
while(left < right)
{
while (left < right && nums[right] > pivot)
right--;
nums[left] = nums[right];
while (left < right && nums[left] <= pivot)
left++;
nums[right] = nums[left];
}
nums[right] = pivot; // 基准值的正确位置
return left; // 返回基准值
}
// 快速排序
public static void quickSort(int[] nums, int left, int right)
{
if (left >= right)
return;
// 分区 --> 分好区之后的基准值的索引
int pivotIndex = randomPartition(nums, left, right);
// 左边的区域, left -> pivotIndex - 1
quickSort(nums, left, pivotIndex - 1);
// 右边的区域,pivotIndex+1->right
quickSort(nums, pivotIndex+1, right);
}
static void Main()
{
int[] test = { 44, 12, 59, 36, 62, 43, 94, 7, 35, 52, 85 };
quickSort(test, 0, test.Length-1);
foreach(int item in test)
{
Console.WriteLine(item);
}
}
}
public class Solution
{
// 合并
public static int[] merge(int[] left, int[] right)
{
// 最终返回一个合并好的有序的数组
// 定义两个变量,分别代表当前left与right的未添加进有序数组的第一个元素
int leftIndex = 0, rightIndex = 0;
List<int> res = new List<int>();
while (leftIndex < left.Length && rightIndex < right.Length)
{
//左边数组的元素小于右边数组
if (left[leftIndex] <= right[rightIndex])
{
// 把左边元素添加到有序区中
res.Add(left[leftIndex]);
// 索引往后移
leftIndex ++;
}
else
{
// 把右边元素添加到有序区中
res.Add(right[rightIndex]);
// 索引往后移
rightIndex ++;
}
}
// 把剩余的未添加的元素全部添加到有序数组后面
foreach (int item in right[rightIndex..])
{
res.Add(item);
}
// 为什么可以直接添加?因为left,right本身就是一个有序数组
foreach (int item in left[leftIndex..])
{
res.Add(item);
}
// 如果说left_idx走完了,right还剩一些元素,说明right剩下的元素全部都比有序数组的最后一个元素要大
return res.ToArray();
}
// 归并排序
public static int[] mergeSort(int[] nums)
{
//数组不能再分了
if (nums.Length <= 1)
return nums;
int mid = nums.Length / 2; // 求出数组的中间位置
int[] left = mergeSort(nums[..mid]);
int[] right = mergeSort(nums[mid..]);
// 合并
return merge(left, right);
}
// 归并排序
static void Main(string[] args)
{
int[] nums = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
int[] result = mergeSort(nums);
foreach(int item in result)
{
Console.WriteLine(item);
}
}
}
public class Program
{
// 计数排序
public static void CountingSort(int[] array)
{
// 长度小于等于0直接return
if (array.Length <= 0)
return;
int min = array[0];
int max = min;
// 找出数组最大元素和最小元素
foreach (int item in array)
{
if (item > max)
{
max = item;
}
else if (item < min)
{
min = item;
}
}
// 把所有元素存入counting数组
int[] counting = new int[max - min + 1];
for (int i = 0; i < array.Length; i++)
{
counting[array[i] - min] += 1;
}
int index = -1;
for (int i = 0; i < counting.Length; i++)
{
for (int j = 0; j < counting[i]; j++)
{
index++;
array[index] = i + min;
}
}
}
public static void Main(string[] args)
{
int[] array = { 43, 69, 11, 72, 28, 21, 56, 80, 48, 94, 32, 8 };
CountingSort(array);
foreach(int item in array)
{
Console.WriteLine(item);
}
}
}
public class Program
{
// 基数排序
public static void RadixSort(int[] array, int bucketNum)
{
int maxLength = MaxLength(array);
//创建bucket时,在二维中增加一组标识位,
//其中bucket[x, 0]表示这一维所包含的数字的个数
//通过这样的技巧可以少写很多代码
int[,] bucket = new int[bucketNum, array.Length + 1];
for (int i = 0; i < maxLength; i++)
{
foreach (var num in array)
{
int bit = (int)(num / Math.Pow(10, i) % 10);
bucket[bit, ++bucket[bit, 0]] = num;
}
for (int count = 0, j = 0; j < bucketNum; j++)
{
for (int k = 1; k <= bucket[j, 0]; k++)
{
array[count++] = bucket[j, k];
}
}
//最后要重置这个标识
for (int j = 0; j < bucketNum; j++)
{
bucket[j, 0] = 0;
}
}
}
private static int MaxLength(int[] array)
{
if (array.Length <= 0)
return 0;
int max = array.Max(); // 取出数组的最大值
return (int)Math.Log10(max) + 1; // 取出位数
}
public static void Main(string[] args)
{
int[] array = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
RadixSort(array, 10);
foreach (int item in array)
{
Console.WriteLine(item);
}
}
}
public class Program
{
// 桶排序
static void BucketSort(int[] array, int bucketsize = 5)
{
int max = array.Max(), min = array.Min(); // 最大值与最小值
int bucketnums = (max - min) / bucketsize + 1; // 分配的桶数量
List<List<int>> buckets = new List<List<int>>();
// 生成桶
for (int i = 0; i < bucketnums; i++)
{
buckets.Add(new List<int>());
}
//将数组的元素放入桶中,并保证桶里是有序的
for (int i = 0; i < array.Length; i++)
{
int bucketIndex = (array[i] - min) / bucketsize;
buckets[bucketIndex].Add(array[i]);
}
int index = 0;
for (int i = 0; i < buckets.Count; i++)
{
buckets[i].Sort(); // 对生成的每个桶排序
for (int j = 0; j < buckets[i].Count; j++)
{
array[index++] = buckets[i][j];
}
}
}
static void Main(string[] args)
{
int[] test = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
BucketSort(test);
foreach(int item in test)
{
Console.WriteLine(item);
}
}
}
class Program
{
// 堆排序
public static void HeapSort(int[] nums)
{
//将最大的值推到堆顶
//x根据最后一个子节点的位置计算出父节点
int x = Convert.ToInt32(Math.Floor(Convert.ToDouble((nums.Length - 2) / 2)));
for (int i = x; i >= 0; i--)
{
//如果子元素只存在左子元素时, 让右子元素等于左子元素
while (nums[i] < nums[i * 2 + 1] || nums[i] < nums[(i * 2 + 2) > (nums.Length - 1) ? (i * 2 + 1) : i * 2 + 2])
{
if (nums[i * 2 + 1] >= nums[(i * 2 + 2) > (nums.Length - 1) ? (i * 2 + 1) : i * 2 + 2])
{
int index = nums[i];
nums[i] = nums[i * 2 + 1];
nums[i * 2 + 1] = index;
}
else
{
int index = nums[i];
nums[i] = nums[i * 2 + 2];
nums[i * 2 + 2] = index;
}
}
}
//输出堆顶最大的元素
int max = nums[0];
nums[0] = nums[nums.Length - 1];
Console.WriteLine(max);
//将数组中的最后一个元素删除
int[] num = new int[nums.Length - 1];
for (int j = 0; j < nums.Length - 1; j++)
{
num[j] = nums[j];
}
Adjust(num);
}
public static void Adjust(int[] nums)
{
if (nums.Length > 1) HeapSort(nums);
else Console.WriteLine("{0}\t", nums[0]);
}
static void Main(string[] args)
{
int[] nums = new int[] { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
Adjust(nums);
}
}
public class Program
{
// 希尔排序
public static void shellSort(int[] nums)
{
int n = nums.Length; // 数组的长度
int gap = n / 2; // 设定一个增量gap
while(gap >= 1)
{
// 分组
for(int i = gap; i < n; i++)
{
int curNum = nums[i]; // 当前要插入的无序区的元素的值
int idx = i - gap; // 当前元素所在小组的有序区的最后一个元素的索引
while (idx >= 0 && curNum < nums[idx]) // 插入排序
{
nums[idx + gap] = nums[idx];
idx -= gap;
}
nums[idx+gap] = curNum;
}
gap /= 2; // 缩小增量
}
}
static void Main(string[] args)
{
int[] test = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
shellSort(test);
foreach(int item in test)
{
Console.WriteLine(item);
}
}
}
排序算法 | 平均时间复杂度 | 最好情况 | 最坏情况 | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O(n2) | O(n) | O(n2) | O(1) | 稳定 |
选择排序 | O(n2) | O(n2) | O(n2) | O(1) | 不稳定 |
插入排序 | O(n2) | O(n) | O(n2) | O(1) | 稳定 |
快速排序 | O(nlogn) | O(nlogn) | O(n2) | O(logn) | 不稳定 |
随机快速排序 | O(n2) | O(nlgn) | O(n2) | O(1) | 不稳定 |
归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 稳定 |
计数排序 | O(n + k) | O(n + k) | O(n + k) | O(k) | 稳定 |
基数排序 | O(n × \times ×k) | O(n × \times ×k) | O(n × \times ×k) | O(n + k) | 稳定 |
桶排序 | O(n + k) | O(n + k) | O(n2) | O(n + k) | 稳定 |
堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不稳定 |
希尔排序 | O(nlogn) | O(nlog2n) | O(nlog2n) | O(1) | 稳定 |
本章部分图文内容来源于网站资料和网友提供, 自己整理收集,方便学习参考,版权属于原作者。