码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2018-01-07 15:56:06      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:body   避免   algo   quic   合并   交换   有序   增量   bre   

  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值放到最终的位置
        }
    }

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

标签:body   避免   algo   quic   合并   交换   有序   增量   bre   

原文地址:https://www.cnblogs.com/dongjh/p/8227778.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!