排序算法2(快速排序,归并排序,基数排序)

本文深入讲解了归并排序、快速排序及基数排序等经典排序算法的主要思想与实现代码。通过对比不同排序方法的特点,帮助读者理解算法的工作原理,并提供详细的代码示例以便实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

排序算法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;
                }
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值