actanble

导航

快速排序和归并排序浅解

本文主要讲解基础排序算法中的快速排序和归并排序;这两种排序是非常非常简单的两个小算法案例。闲来被小伙伴问了一下,于是就对这两个算法的内容进行一个讲解。

快速排序

快速排序的背景和性能就不加赘述了,这里就介绍一下,在知道想法之后,一些小伙伴也会困扰和出错的地方。

算法讲解

通过待排序的元素和排序好的序列进行插入,依次进行。
例如: a1,a2,a3,a4已经排列好了,那么插入进来的a5,应该放在其中哪个位置;
一般的方法就是依次从右往左遍历,直到找到了适合插入的位置,此时正好大于等于前面一个元素ak。接着是让比它大的元素右移。这里有的同学经常用的交换,也可以;

快排程序示例1

int quickSort2(int arr[],size_t n){
    for(int i=0;i != n-1; ++i){
        int k = i+1;
        int next = arr[i+1];
        while(arr[k-1]> next && k>-1){
            arr[k] = arr[k-1];
            k--;
        }
        arr[k] = next;
    }
    return 0;
}

快排的时间复杂度是O(nlog2(n)),在最坏的情况下就是O(n2)
为了便于理解对这个一般的方法可以进行一个小小的改良,例如在找到合适的位置插入的过程中,我们使用二分查找,那么二分查找的复杂度O(log2(n)), 正好外面一层是O(n), 所以进行一个嵌套之后就知道了,是O(nlog2(n))

快速排序程序示例

可以在上面k值待插时,使用二分查找的想法; 这里返回待插入的位置。并且保证稳定性。二分查找示例。

int binFind(const int arr[],int start,int end,int key){
    int left,right;
    int mid;
    left=start;
    right=end;
    while(left<=right){
        mid=(left+right)/2;
        if(key==arr[mid])  return mid+1;
        else if(key < arr[mid]) right=mid-1;
        else if(key>arr[mid]) left=mid+1;
    }
    return left;//没找到这个元素,正好错过去了;那么就返回left的角标
}

归并排序

归并的背景和性能也不加赘述了,这里就介绍一下,常见的困扰地方或者复写容易出错的地方。

算法讲解

通过分治的想法对数列进行排序。
什么叫分治?分治就是把问题分解为一个个非常小的规模,解决之后再合并起来组成全局问题的解。
很显然,归排就是这样的一个经典例子。
A1:首先任何一个数列都可以依次分裂成两半, 两半中的任意一半又可以分裂成均匀两半,直到都分解到非常小的规模后,再进行比较;
A2:当规模足够小的时候,可以想到总会出现像二叉树一样的结构;依次从根部层序向上归并。在这里分离出一个功能函数Merge()来维护;
B1:可以看到这个程序是一个从上往底,从底往上的一个过程;内部是用递归维持的,这个结构也就是二叉树的结构;所以时间复杂度是O(nlog2(n)), 这个就不加赘述了。

归排程序示例

int Merge(int arr[],int tempArr[], int start, int mid, int end){
    int i = start, j=mid+1, k = start;
    while(i!=mid+1 && j!=end+1){
        if(arr[i] > arr[j])
            tempArr[k++] = arr[j++];
        else
            tempArr[k++] = arr[i++];
    }
    while(i != mid +1)
        tempArr[k++] = arr[i++];
    while(j != end+1)
        tempArr[k++] = arr[j++];
    for(i=start; i<=end; i++)
        arr[i] = tempArr[i];
    return 0;
}

int MergeSort(int arr[], int tempArr[], int start, int end){
    int mid;
    if(start < end){
        mid = (start + end) / 2;
        MergeSort(arr, tempArr, start, mid);
        MergeSort(arr, tempArr, mid+1, end);
        Merge(arr, tempArr, start, mid, end);
    }
    return 0;
}

上面两种方法可以看到本质上非常接近,至于O(log2(n))可以直观了解到,有二分查找,有递归或者树结构; 有兴趣的关于更多排序方法可以在wiki百科中查找到;

posted on 2016-10-30 22:59  白于空  阅读(322)  评论(0编辑  收藏  举报