对比快速排序,理解归并排序

对比快速排序来理解归并排序。

有时经常讲归并排序和快速排序记混乱,因为两者都用到了分治法。其实两者的不同之处非常明显。

快速排序:“先治后分”,

void quickly_sort(int arr[], int low, int high) {
  if (low < high) {
    // 先治后分
    int pivot = _qucikly_sort(arr, low, high);  //治
    quickly_sort(arr, low, pivot-1); //分
    quickly_sort(arr, pivot + 1, high); //分
  }
}

归并排序:“先分后治”。

void merge_sort_up2down(int a[], int start, int end) {
    if(a==NULL || start >= end)
        return ;
    // 先分后治
    int mid = (end + start)/2;
    merge_sort_up2down(a, start, mid); // 分
    merge_sort_up2down(a, mid+1, end); // 分
    merge(a, start, mid, end); // 治
}

“分”的过程用递归实现起来分简单,主要是理解两者的“治”。

快速排序的根本处理是:如何在选定一个元素后,将这个元素放在合适的位置,使得元素左边都是小于这个元素的,右边都是大于这个元素的(挖坑填坑法)

int _qucikly_sort(int arr[], int low, int high) {
  int pivot = arr[low]; //挖第一个坑,把“萝卜”放进篮子
  while(low<high) { //开始循环挖坑填坑
    //如果low等于high,说明找坑的过程中,找到了上一次挖的坑,因此可以停止了
    while(low<high && arr[high]>=pivot) //从右边往左边找填坑的元素(比pivot小的元素)。 2,4,6的过程
      --high;
    arr[low] = arr[high]; //将找到之后,挖出来,填到左边的坑里
    while(low<high && arr[low]<=pivot) //从左边往右边找填坑的(比pivot大的元素)。3,5的过程
      ++low;
arr[high] = arr[low];//找到之后,填到右边的坑里
  }
  arr[low] = pivot; //篮子里的“萝卜”填到坑里
  return low;//返回这个坑的位置,作为分而治之的中轴
}

归并排序的根本处理是:如何将两个有序的数组,合并成一个有序数组(申请一个数组,大小是两个有序数组(原数组的两个子数组)的大小之和,遍历比较两个数组的元素,按大小放进新数组,将新数组替换原数组的子数组即可):

void merge(int a[], int start, int mid, int end) {
    int *tmp = (int *)malloc((end-start+1)*sizeof(int));    // tmp是汇总2个有序区的临时区域
    int i = start;            // 第1个有序区的索引
    int j = mid + 1;        // 第2个有序区的索引
    int k = 0;                // 临时区域的索引

    while(i <= mid && j <= end) {
        if (a[i] <= a[j])
            tmp[k++] = a[i++];
        else
            tmp[k++] = a[j++];
    }

    while(i <= mid)
        tmp[k++] = a[i++];

    while(j <= end)
        tmp[k++] = a[j++];

    // 将排序后的元素,全部都整合到数组a中。
    for (i = 0; i < k; i++)
        a[start + i] = tmp[i];

    free(tmp);
}


这样,都过简单的代码对比,就可以很简单的分清楚两者的关系与不同。


  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值