• 经典算法学习——高速排序


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

    排序效率在同为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

  • 相关阅读:
    openldap
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P1567 统计天数
    Java实现 洛谷 P1567 统计天数
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7281715.html
Copyright © 2020-2023  润新知