快速排序和归并排序浅解

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

快速排序

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

算法讲解

通过待排序的元素和排序好的序列进行插入,依次进行。
例如: 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百科中查找到;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值