240505-基础算法-排序【未完待续】

本文主要内容:

  1. 插入排序
  2. 选择排序
  3. 冒泡排序
  4. 快速排序
  5. 归并排序
  6. 堆排序
  7. 基数排序
  8. 希尔排序
  9. 计数排序
  10. 桶排序

本文所有代码均使用C#编写
240505天气:小雨转多云


算法总结图1

在这里插入图片描述

1 插入排序2

插入排序(Insertion Sort):将序列分为已排序和未排序两部分,从未排序的部分选择元素插入到已排序的部分中,直到所有元素都被插入到已排序的部分。时间复杂度O(n2)。

void InsertSort(int[] nums)
{
    int n = nums.Length;
    for(int i = 1; i < n; i++)
    {
        int t = nums[i];
        int j = i;
        while(j > 0 && nums[j - 1] > t)
        {
            nums[j] = nums[j - 1];
            j--;
        }
        nums[j] = t;
    }
}

2 选择排序

从序列中选择最小的元素,放到序列的起始位置,再从剩余元素中选择最小的元素放到已排序序列的末尾。时间复杂度O(n2)。

void SelectSort(int[] nums)
{
    int n = nums.Length;
    for(int i = 0; i < n - 1; i++)
    {
        int minIndex = i;
        for(int j = i + 1; j < n; j++)
            if(nums[j] < nums[minIndex])
                minIndex = j;
        (nums[minIndex], nums[i]) = (nums[i], nums[minIndex]);
    }
}

3 冒泡排序

相邻元素比较,逐步将最大元素“冒泡”到序列最后。时间复杂度O(n^2)。

void BubbleSort(int[] nums)
{
    int n = nums.Length;
    for(int i = 0; i < n - 1; i++)
        for(int j = 0; j < n - 1 - i; j++)
            if(nums[j] > nums[j + 1])
                (nums[j], nums[j + 1]) = (nums[j + 1], nums[j]);
}

4 快速排序

1.基于分治的思想
2.先在递归区间内找到一个元素作为枢轴(pivot),将该区间处理成所有数小于等于pivot和所有数大于等于pivot的两个子区间
3.继续递归处理两个子区间,直到子区间长度小于等于1时结束递归

void QuickSort(int[] nums, int l, int r)
{
    if(l >= r)return;
    int i = l, j = r;
    int pivot = nums[l];
    while(i < j)
    {
        while(i < j && nums[j] >= pivot)j--;//前
        while(i < j && nums[i] <= pivot)i++;//后
        if(i < j)
            (nums[i], nums[j]) = (nums[j], nums[i]);
    }
    nums[l] = nums[i];
    nums[i] = pivot;
    QuickSort(nums, l, i - 1);
    QuickSort(nums, i + 1, r);
}

5 归并排序

1.基于分治的思想
2.将数组区间一分为而,先递归排序左子区间,再递归排序右子区间
3.将两个已经排好序的子区间归并成一个有序数组,然后结束递归

void MergeSort(int[] nums, int left, int right)
{
    if(left >= right)
        return;
    int midIndex = left + right >> 1;
    MergeSort(nums, left, midIndex);
    MergeSort(nums, midIndex + 1, right);
    int[] tempArr = new int[nums.Length];
    for(int i = 0; i < nums.Length; i++)
        tempArr[i] = nums[i];
    int p = left, q = midIndex + 1, r = left;
    while(p <= midIndex && q <= right)
    {
        if(tempArr[p] <= tempArr[q])
            nums[r++] = tempArr[p++];
        else
            nums[r++] = tempArr[q++];
    }
    while(p <= midIndex)
        nums[r++] = tempArr[p++];
    while(q <= right)
        nums[r++] = tempArr[q++];
}

6 堆排序

将数组存入小根堆中,第1次取出的堆顶元素就是最小的,然后移除堆顶元素,第2次取出的堆顶元素就是第2小的,以此类推

void HeapSort(int[] nums)
{
    int n = nums.Length;
    int[] myHeap = new int[n];
    int myHeapSize = myHeap.Length;
    for(int i = 0; i < n; i++)
        myHeap[i] = nums[i];
    for(int i = n / 2; i >= 0; i--)
        Down(myHeap, i, myHeapSize);
    for(int i = 0; i < n; i++)
    {
        nums[i] = myHeap[0];
        (myHeap[0], myHeap[myHeapSize - 1]) = (myHeap[myHeapSize - 1], myHeap[0]);
        myHeapSize--;
        Down(myHeap, 0, myHeapSize);
    }

}
//下沉
void Down(int[] myHeap, int curIndex, int myHeapSize)
{
    int minIndex = curIndex;
    int leftSon = curIndex * 2, rightSon = curIndex * 2 + 1;
    if(leftSon < myHeapSize && myHeap[leftSon] < myHeap[minIndex])
        minIndex = leftSon;
    if(rightSon < myHeapSize && myHeap[rightSon] < myHeap[minIndex])
        minIndex = rightSon;
    if(minIndex != curIndex)
    {
        (myHeap[curIndex], myHeap[minIndex]) = (myHeap[minIndex], myHeap[curIndex]);
        Down(myHeap, minIndex, myHeapSize);
    }
}

7 基数排序

将待排序的整数拆分成多个数字位上的值,然后从最低位到最高位依次对每个数字位上的值进行排序。

在这里插入图片描述
练习题:164. 最大间距

void RadixSort(int[] nums) 
 {
    int n = nums.Length;
    int exp = 1;
    int[] numCnt = new int[10];
    int[,] tempSet = new int[10,n];
    for(int i = 0; i < 10; i++){
        for(int j = 0; j < n; j++){
            int k = (nums[j] / exp) % 10;
            tempSet[k,numCnt[k]] = nums[j];
            numCnt[k]++;
        }
        for(int j = 0, t = 0; j < 10; j++){
            
            for(int k = 0; k < numCnt[j]; k++){
                nums[t++] = tempSet[j,k];
            }
            numCnt[j] = 0;
        }
        exp *= 10;
    }
}

8 希尔排序

参考:十大经典排序算法最强总结(含JAVA代码实现)

对插入排序的一种优化。将数组分为gap个组,组内进行插入排序,然后缩小分组,继续进行插入排序,最后整个数组分为1个组,进行插入排序时移动元素的次数会减少很多

void ShellSort(int[] nums)
{
    int n = nums.Length;
    int gap = n / 2;
    while(gap > 0)
    {
        for(int i = gap; i < n; i++)
        {
            int temp = nums[i];
            int j = i;
            while(j - gap >= 0 && nums[j - gap] > temp)
            {
                nums[j] = nums[j - gap];
                j -= gap;
            }
            nums[j] = temp;
        }
        gap /= 2;
    }
}

9 计数排序

将原数组中每个数nums[i]出现的次数保存到另一个数组中count[],数组下标就为nums[i],数组值为nums[i]出现的次数,然后根据count[]来对原数组nums[]进行排序

void CountingSort(int[] nums)
{
    int n = nums.Length;
    if(n < 1)
        return;
    int minNum = nums[0];
    int maxNum = nums[0];
    foreach(int num in nums)
    {
        minNum = Math.Min(minNum, num);
        maxNum = Math.Max(maxNum, num);
    }
    int range = maxNum - minNum + 1;
    int[] count = new int[range];
    foreach(int num in nums)
        count[num - minNum]++;
    for(int i = 1; i < range; i++)
        count[i] += count[i - 1];
    int[] temp = new int[n];
    foreach(int num in nums)
    {
        int index = count[num - minNum] - 1;
        temp[index] = num;
        count[num - minNum]--;
    }
    Array.Copy(temp, nums, nums.Length);
}

10 桶排序

桶排序可以看做时计数排序的一种优化,计数排序可以看做单个元素作为1个桶的桶排序,桶排序一般以区间作为桶的宽度(即每个桶能装的元素种类数)。
桶排序的原理是将原数组分为若干段,每一段元素丢到一个桶中,再对每个桶分别排序,最后将各个桶中的元素从头到尾连起来

void BucketSort(int[] nums)
{
    int n = nums.Length;
    if(n < 1)
        return;
    int minNum = nums[0];
    int maxNum = nums[0];
    for(int i = 1; i < n; i++)
    {
        minNum = Math.Min(minNum, nums[i]);
        maxNum = Math.Max(maxNum, nums[i]);
    }
    int range = maxNum - minNum;
    int bucketCount = range / n + 1;
    List<List<int>> buckets = new List<List<int>>(bucketCount);

    for(int i = 0; i < bucketCount; i++)
        buckets.Add(new List<int>());
    
    foreach(int num in nums)
    {
        int bucketIndex = (num - minNum) / n;
        buckets[bucketIndex].Add(num);
    }

    buckets.ForEach((List<int> list)=> list.Sort());

    int numsIndex = 0;
    for(int i = 0; i < bucketCount; i++)
    {
        List<int> bucket = buckets[i];
        bucket.ForEach((int num) => nums[numsIndex++] = num);
    }
}

10个排序算法完整代码(C#)

using System.Net;

int[] nums = {125, 16, 214, 111, 2, 30};


void InsertSort(int[] nums)
{
    int n = nums.Length;
    for(int i = 1; i < n; i++)
    {
        int t = nums[i];
        int j = i;
        while(j > 0 && nums[j - 1] > t)
        {
            nums[j] = nums[j - 1];
            j--;
        }
        nums[j] = t;
    }
}

void SelectSort(int[] nums)
{
    int n = nums.Length;
    for(int i = 0; i < n - 1; i++)
    {
        int minIndex = i;
        for(int j = i + 1; j < n; j++)
            if(nums[j] < nums[minIndex])
                minIndex = j;
        (nums[minIndex], nums[i]) = (nums[i], nums[minIndex]);
    }
}

void BubbleSort(int[] nums)
{
    int n = nums.Length;
    for(int i = 0; i < n - 1; i++)
        for(int j = 0; j < n - 1 - i; j++)
            if(nums[j] > nums[j + 1])
                (nums[j], nums[j + 1]) = (nums[j + 1], nums[j]);
}

void QuickSort(int[] nums, int l, int r)
{
    if(l >= r)return;
    int i = l, j = r;
    int pivot = nums[l];
    while(i < j)
    {
        while(i < j && nums[j] >= pivot)j--;
        while(i < j && nums[i] <= pivot)i++;
        if(i < j)
            (nums[i], nums[j]) = (nums[j], nums[i]);
    }
    nums[l] = nums[i];
    nums[i] = pivot;
    QuickSort(nums, l, j - 1);
    QuickSort(nums, j + 1, r);
}

void MergeSort(int[] nums, int left, int right)
{
    if(left >= right)
        return;
    int midIndex = left + right >> 1;
    MergeSort(nums, left, midIndex);
    MergeSort(nums, midIndex + 1, right);
    int[] tempArr = new int[nums.Length];
    for(int i = 0; i < nums.Length; i++)
        tempArr[i] = nums[i];
    int p = left, q = midIndex + 1, r = left;
    while(p <= midIndex && q <= right)
    {
        if(tempArr[p] <= tempArr[q])
            nums[r++] = tempArr[p++];
        else
            nums[r++] = tempArr[q++];
    }
    while(p <= midIndex)
        nums[r++] = tempArr[p++];
    while(q <= right)
        nums[r++] = tempArr[q++];
}


void HeapSort(int[] nums)
{
    int n = nums.Length;
    int[] myHeap = new int[n];
    int myHeapSize = myHeap.Length;
    for(int i = 0; i < n; i++)
        myHeap[i] = nums[i];
    for(int i = n / 2; i >= 0; i--)
        Down(myHeap, i, myHeapSize);
    for(int i = 0; i < n; i++)
    {
        nums[i] = myHeap[0];
        (myHeap[0], myHeap[myHeapSize - 1]) = (myHeap[myHeapSize - 1], myHeap[0]);
        myHeapSize--;
        Down(myHeap, 0, myHeapSize);
    }

}

void Down(int[] myHeap, int curIndex, int myHeapSize)
{
    int minIndex = curIndex;
    int leftSon = curIndex * 2, rightSon = curIndex * 2 + 1;
    if(leftSon < myHeapSize && myHeap[leftSon] < myHeap[minIndex])
        minIndex = leftSon;
    if(rightSon < myHeapSize && myHeap[rightSon] < myHeap[minIndex])
        minIndex = rightSon;
    if(minIndex != curIndex)
    {
        (myHeap[curIndex], myHeap[minIndex]) = (myHeap[minIndex], myHeap[curIndex]);
        Down(myHeap, minIndex, myHeapSize);
    }
}

 void RadixSort(int[] nums) 
 {
    int n = nums.Length;
    int exp = 1;
    int[] numCnt = new int[10];
    int[,] tempSet = new int[10,n];
    for(int i = 0; i < 10; i++){
        for(int j = 0; j < n; j++){
            int k = (nums[j] / exp) % 10;
            tempSet[k,numCnt[k]] = nums[j];
            numCnt[k]++;
        }
        for(int j = 0, t = 0; j < 10; j++){
            
            for(int k = 0; k < numCnt[j]; k++){
                nums[t++] = tempSet[j,k];
            }
            numCnt[j] = 0;
        }
        exp *= 10;
    }
}

void ShellSort(int[] nums)
{
    int n = nums.Length;
    int gap = n / 2;
    while(gap > 0)
    {
        for(int i = gap; i < n; i++)
        {
            int temp = nums[i];
            int j = i;
            while(j - gap >= 0 && nums[j - gap] > temp)
            {
                nums[j] = nums[j - gap];
                j -= gap;
            }
            nums[j] = temp;
        }
        gap /= 2;
    }
}

void CountingSort(int[] nums)
{
    int n = nums.Length;
    if(n < 1)
        return;
    int minNum = nums[0];
    int maxNum = nums[0];
    foreach(int num in nums)
    {
        minNum = Math.Min(minNum, num);
        maxNum = Math.Max(maxNum, num);
    }
    int range = maxNum - minNum + 1;
    int[] count = new int[range];
    foreach(int num in nums)
        count[num - minNum]++;
    for(int i = 1; i < range; i++)
        count[i] += count[i - 1];
    int[] temp = new int[n];
    foreach(int num in nums)
    {
        int index = count[num - minNum] - 1;
        temp[index] = num;
        count[num - minNum]--;
    }
    Array.Copy(temp, nums, nums.Length);
}

void BucketSort(int[] nums)
{
    int n = nums.Length;
    if(n < 1)
        return;
    int minNum = nums[0];
    int maxNum = nums[0];
    for(int i = 1; i < n; i++)
    {
        minNum = Math.Min(minNum, nums[i]);
        maxNum = Math.Max(maxNum, nums[i]);
    }
    int range = maxNum - minNum;
    int bucketCount = range / n + 1;
    List<List<int>> buckets = new List<List<int>>(bucketCount);

    for(int i = 0; i < bucketCount; i++)
        buckets.Add(new List<int>());
    
    foreach(int num in nums)
    {
        int bucketIndex = (num - minNum) / n;
        buckets[bucketIndex].Add(num);
    }

    buckets.ForEach((List<int> list)=> list.Sort());

    int numsIndex = 0;
    for(int i = 0; i < bucketCount; i++)
    {
        List<int> bucket = buckets[i];
        bucket.ForEach((int num) => nums[numsIndex++] = num);
    }
}

// InsertSort(nums);
// SelectSort(nums);
// BubbleSort(nums);
// QuickSort(nums, 0, nums.Length - 1);
// MergeSort(nums, 0, nums.Length - 1);
// HeapSort(nums);
// RadixSort(nums);
// ShellSort(nums);
// CountingSort(nums);
BucketSort(nums);
for(int i = 0; i < nums.Length; i++)
    Console.Write(nums[i] + " ");

参考资料:


  1. https://www.cnblogs.com/guoyaohua/p/8600214.html ↩︎

  2. https://blog.csdn.net/weixin_64600209/article/details/131354250?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-3-131354250.nonecase&spm=1018.2226.3001.4187 ↩︎

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值