七种基本排序算法(希尔排序,直接插入排序,冒泡排序,快速排序,简单选择排序,归并排序,堆排序)

Posted Code Dog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了七种基本排序算法(希尔排序,直接插入排序,冒泡排序,快速排序,简单选择排序,归并排序,堆排序)相关的知识,希望对你有一定的参考价值。

  class SortAlgorithm
    {
        static void Main(string[] args)
        {
            int[] arr1 = { 1, 4, 2, 7, 9, 8, 3, 6 };
            //ShellSort(arr1);
            //DirectInsertSort(arr1);
            //BubbleSort(arr1);
            //QuickSort(arr1, 0, arr1.Length - 1);
            //SimpleSelectSort(arr1);
            //MergeSort(arr1);
            //HeapSort(arr1);
            Console.Read();
        }

        public static void DirectInsertSort(int[] arr)
        {
            for (int i = 1; i < arr.Length; i++)
            {
                if (arr[i] < arr[i - 1])
                {//注意[0,i-1]都是有序的。如果待插入元素比arr[i-1]还大则无需再与[i-1]前面的元素进行比较了,反之则进入if语句
                    int temp = arr[i];
                    int j;
                    for (j = i - 1; j >= 0 && arr[j] > temp; j--)
                    {
                        arr[j + 1] = arr[j];//把比temp大或相等的元素全部往后移动一个位置            
                    }
                    arr[j + 1] = temp;//把待排序的元素temp插入腾出位置的(j+1)
                }
            }
        }

        public static void ShellSort(int[] arr)
        {
            //增量gap,并逐步缩小增量
            for (int gap = arr.Length / 2; gap > 0; gap /= 2)
            {
                //从第gap个元素,逐个对其所在组进行直接插入排序操作
                for (int i = gap; i < arr.Length; i++)
                {
                    int j = i;
                    int temp = arr[j];
                    if (arr[j] < arr[j - gap])
                    {
                        while (j - gap >= 0 && temp < arr[j - gap])
                        {
                            //移动法
                            //arr[j] = arr[j - gap];
                            //插入排序采用交换法
                            swap(arr, j, j - gap);

                            j -= gap;
                        }
                        arr[j] = temp;
                    }
                }
            }
        }

        public static void swap(int[] arr, int a, int b)
        {
            arr[a] = arr[a] + arr[b];
            arr[b] = arr[a] - arr[b];
            arr[a] = arr[a] - arr[b];
        }

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

        public static void SimpleSelectSort(int[] arr)
        {
            for (int i = 0; i < arr.Length - 1; i++)
            {
                int min = i;//每一趟循环比较时,min用于存放较小元素的数组下标,这样当前批次比较完毕最终存放的就是此趟内最小的元素的下标,避免每次遇到较小元素都要进行交换。
                for (int j = i + 1; j < arr.Length; j++)
                {
                    if (arr[j] < arr[min])
                    {
                        min = j;
                    }
                }
                //进行交换,如果min发生变化,则进行交换
                if (min != i)
                {
                    swap(arr, min, i);
                }
            }
        }

        public static void QuickSort(int[] arr, int _left, int _right)
        {
            int left = _left;
            int right = _right;
            int temp = 0;
            if (left <= right)
            {   //待排序的元素至少有两个的情况
                temp = arr[left];  //待排序的第一个元素作为基准元素
                while (left != right)
                {   //从左右两边交替扫描,直到left = right

                    while (right > left && arr[right] >= temp)
                        right--;        //从右往左扫描,找到第一个比基准元素小的元素
                    arr[left] = arr[right];  //找到这种元素arr[right]后与arr[left]交换

                    while (left < right && arr[left] <= temp)
                        left++;         //从左往右扫描,找到第一个比基准元素大的元素
                    arr[right] = arr[left];  //找到这种元素arr[left]后,与arr[right]交换
                }
                arr[right] = temp;    //基准元素归位
                QuickSort(arr, _left, left - 1);  //对基准元素左边的元素进行递归排序
                QuickSort(arr, right + 1, _right);  //对基准元素右边的进行递归排序
            }
        }

        public static void MergeSort(int[] arr)
        {
            int[] temp = new int[arr.Length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
            MergeSort(arr, 0, arr.Length - 1, temp);
        }
        private 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);//将两个有序子数组合并操作
            }
        }
        private 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中
                temp[t++] = arr[i++];
            }
            while (j <= right)
            {//将右序列剩余元素填充进temp中
                temp[t++] = arr[j++];
            }
            t = 0;
            //将temp中的元素全部拷贝到原数组中
            while (left <= right)
            {
                arr[left++] = temp[t++];
            }
        }

        public static void HeapSort(int[] arr)
        {
            //1.构建大顶堆
            for (int i = arr.Length / 2 - 1; i >= 0; i--)
            {
                //从第一个非叶子结点从下至上,从右至左调整结构
                adjustHeap(arr, i, arr.Length);
            }
            //2.调整堆结构+交换堆顶元素与末尾元素
            for (int j = arr.Length - 1; j > 0; j--)
            {
                swap(arr, 0, j);//将堆顶元素与末尾元素进行交换
                adjustHeap(arr, 0, j);//重新对堆进行调整
            }

        }

        /**
         * 调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上)
         * @param arr
         * @param i
         * @param length
         */
        public static void adjustHeap(int[] arr, int i, int length)
        {
            int temp = arr[i];//先取出当前元素i
            for (int k = i * 2 + 1; k < length; k = k * 2 + 1)
            {//从i结点的左子结点开始,也就是2i+1处开始
                if (k + 1 < length && arr[k] < arr[k + 1])
                {//如果左子结点小于右子结点,k指向右子结点
                    k++;
                }
                if (arr[k] > temp)
                {//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
                    arr[i] = arr[k];
                    i = k;
                }
                else
                {
                    break;
                }
            }
            arr[i] = temp;//将temp值放到最终的位置
        }
    }

以上是关于七种基本排序算法(希尔排序,直接插入排序,冒泡排序,快速排序,简单选择排序,归并排序,堆排序)的主要内容,如果未能解决你的问题,请参考以下文章

Python八大算法的实现,插入排序希尔排序冒泡排序快速排序直接选择排序堆排序归并排序基数排序。

排序算法学习(直接插入排序,希尔排序,选择排序,堆排序,冒泡排序)

数据结构c语言版八大算法(上)图文详解带你快速掌握——希尔排序,堆排序,插入排序,选择排序,冒泡排序!

基于比较的七种常见排序算法

基于比较的七种常见排序算法

基于比较的七种常见排序算法