zoukankan      html  css  js  c++  java
  • 经典算法学习——高速排序

           高速排序应该算是在面试笔试中最经常使用的算法了。各位面试官都非常喜欢。

    排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被採用。当中的思想也是用了分治法和递归的思想。演示样例代码上传到:https://github.com/chenyufeng1991/QuickSort

    算法的基本思想是:

    (1)先从数列中取出一个数作为基准数(经常选第一个数);

    (2)分区过程,小于或等于的数全放到它的左边,比这个数大的数放到它的右边;

    (3)再对左右区间反复第二步,直到每一个区间仅仅有一个数为止,即左边界下标等于右边界下标;


    简化描写叙述为:

    1.i= L, j=R,基准数即为a[i],保存起来;

    2.j--,由后向前找比它小的数。找到后将此数放到a[i]中;

    3.i++,由前向后找比它大的数。找到后将此数填入到a[j]中;

    4.递归运行2,3两步,直到i==j。最后将基准数填入a[i]中;

    详细代码实现例如以下:

    //
    //  main.c
    //  QuickSort
    //
    //  Created by chenyufeng on 16/1/27.
    //  Copyright © 2016年 chenyufengweb. All rights reserved.
    //
    
    #include <stdio.h>
    
    int *quickSort(int arr[],int l,int r);
    void quickSort02(int *arr,int l,int r);
    
    int main(int argc, const char * argv[]) {
    
        int numArr[5] = {3,6,0,9,4};
    
        //使用指针返回数组。返回的事实上是数组的头指针。
        /**
         *  使用返回指针;
         */
    
    //    int *retArr;
    //    retArr = quickSort(numArr, 0, 4);
    //    for (int i = 0; i < 5; i++) {
    //        //取数组值
    //        printf("%d ",*(retArr + i));
    //    }
    
    
        /**
         *  直接传递引用,比較方便;
         */
        quickSort02(numArr, 0, 4);
        for (int i = 0; i < 5; i++) {
            printf("%d ",numArr[i]);
        }
    }
    
    int *quickSort(int arr[],int l,int r){
        //当左右指针相等的时候直接返回;
        if (l < r) {
            //此时的x就是基准值。
            int i = l,j = r,x = arr[l];
    
            //以下的while循环表示一次分治。也就是进行一次排序;
            while (i < j) {
                //先从基准值右側找出小于基准的值;
                while (i < j && arr[j] >= x) {
                    j--;
                }
                if (i < j) {
                    //交换顺序。i++;
                    arr[i++] = arr[j];
                }
    
                //从基准值左側找出大于基准的值;
                while (i < j && arr[i] < x) {
                    i++;
                }
                if (i < j) {
                    //交换顺序。j--;
                    arr[j--] = arr[i];
                }
            }
            //把基准值放入arr[i]位置。
            arr[i] = x;
            //递归,左右两側分别进行快排。
            quickSort(arr, l, i - 1);
            quickSort(arr, i + 1, r);
        }
        return arr;
    }
    
    void quickSort02(int *arr,int l,int r){
        //当左右指针相等的时候直接返回;
        if (l < r) {
            //此时的x就是基准值;
            int i = l,j = r,x = arr[l];
    
            //以下的while循环表示一次分治,也就是进行一次排序;
            while (i < j) {
                //先从基准值右側找出小于基准的值;
                while (i < j && arr[j] >= x) {
                    j--;
                }
                if (i < j) {
                    //交换顺序,i++;
                    arr[i++] = arr[j];
                }
    
                //从基准值左側找出大于基准的值;
                while (i < j && arr[i] < x) {
                    i++;
                }
                if (i < j) {
                    //交换顺序,j--;
                    arr[j--] = arr[i];
                }
            }
            //把基准值放入arr[i]位置;
            arr[i] = x;
            //递归,左右两側分别进行快排。
            quickSort(arr, l, i - 1);
            quickSort(arr, i + 1, r);
        }
    }
    
    
    
    


    -----------------------------------------------------------------------------------------------------------------------------------------切割线----------------------------------------------------------------

    我们经常写一个Partition函数来做划分。该函数能够用在其它非常多的算法题上。比方一个数组中超过一半的数,数组中第k大的数等。

    以下代码将会更加清晰易懂。

    个人推荐使用以下的实现。

    //
    //  main.c
    //  QuickSort
    //
    //  Created by chenyufeng on 16/1/27.
    //  Copyright © 2016年 chenyufengweb. All rights reserved.
    //
    
    #include <stdio.h>
    
    void QuickSort(int *arr, int start, int end);
    int Partition(int *arr, int start, int end);
    
    int main(int argc, const char * argv[])
    {
        int numArr[7] = {3,6,0,9,4,2,100};
    
        QuickSort(numArr, 0, 6);
    
        for (int i = 0; i < 7; i++)
        {
            printf("%d ",numArr[i]);
        }
    }
    
    void QuickSort(int *arr, int start, int end)
    {
        if (start == end)
        {
            return;
        }
    
        int index = Partition(arr, start, end);
        if (index > start)
        {
            QuickSort(arr, start, index - 1);
        }
        if (index < end)
        {
            QuickSort(arr, index + 1, end);
        }
    }
    
    // 划分算法
    int Partition(int *arr, int start, int end)
    {
        //此时的x就是基准值;
        int i = start, j = end, x = arr[start];
    
        //以下的while循环表示一次分治。也就是进行一次排序;
        while (i < j)
        {
            //先从基准值右側找出小于基准的值。
            while (i < j && arr[j] >= x)
            {
                j--;
            }
            if (i < j)
            {
                //交换顺序,i++。
                arr[i++] = arr[j];
            }
            //从基准值左側找出大于基准的值。
            while (i < j && arr[i] < x)
            {
                i++;
            }
            if (i < j)
            {
                //交换顺序,j--;
                arr[j--] = arr[i];
            }
        }
        //把基准值放入arr[i]位置。
        arr[i] = x;
    
        return i;
    }




         说明一下:高速排序的时间复杂度为O(N*logN),空间复杂度为O(N*logN),是不稳定排序。



    本文參考:http://blog.csdn.net/morewindows/article/details/6684558

  • 相关阅读:
    开关门(结构体)
    洗牌问题(找规律)
    七夕节(hd1215)干嘛今天做这题T_T
    三角形(hd1249)
    寒冰王座(hd1248)
    钱币兑换问题(hd1284)
    计算机模拟(hd1283)
    回文数猜想(hd1282)
    贪吃蛇代码
    变形课hd1181(DFS)
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7281715.html
Copyright © 2011-2022 走看看