C#实现十大排序算法

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

//by Alexander 

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;//继续下一次循环入桶出桶
            }
        }
    }
}


参考链接



作者:艾孜尔江

posted @ 2020-10-08 22:37  艾孜尔江  阅读(402)  评论(0编辑  收藏  举报