排序——快排+归并排序 简述

排序

快排是不稳定的,归并是稳定的

快速排序 主要思想:分治(分界点从数组里随机取一个点

主要流程

  1. 确定分界点

    • 第一种方法:取左边界 q[ I ]
    • 第二种方式:取中间值 q[ ( 1 + r) / 2]
    • 第三种方式 取右边界 q[ r ]
  2. 调整区间

    ​ 使第一个区间里的数都 小于等于 x (左半边

    ​ 第二个区间里的数都 大于等于 x (右半边

  3. 递归处理左右两端

    ​ 左边排好序,右边排好序

第二步中两个小方法

方法一:

  • 设两个数组 a[ ] b[ ]

  • 检查q[ l~r ]的数值

    • 小于等于X的插到a[ ]里
    • 大于等于X的插到b[ ]里
  • 分别将a[ ]、b[ ]插到q[ ]的第一区间和第二区间

方法二:

  • 设置两个指针low和high,他们的初值分别为s和t。首先将X移至临时变量,之后检测指针high所指记录,若q[ high ] 大于 X,则high减1,否则将q[ high ] 移至指针low所指向的位置;之后检查指针low所指记录,若q[ low ] 小于 X ,则 low 增 1,否则将q[ low ] 移至指针high所指位置;重复上述两个方向的检测,直到high和low指针指向同一位置
void quick_sort(int q[], int l, int r)
{
    if (l >= r) return;

    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while (i < j)
    {
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }
    quick_sort(q, l, j), quick_sort(q, j + 1, r);
}

归并排序 主要思想:分治(以中间点为分解点) (分治方法和快排不同

主要流程

  1. 确定分界点 : mid = (1 + r) / 2 (左右两边的平均值,就是最中间的位置
  2. 递归排序 left(第一个序列) 和 right (第二个序列)
  3. 归并 --》 把两个有序的数组合二为一 此步骤的时间复杂度是O(n)

在这里插入图片描述

如何归并

首先通过递归排序保证两个序列都是有序的,设置一个新的数组res[ ] ,和两个指针分别指向两个序列的最小值。比较两个指针指向的数值,把较小的指针指向的数值保存到res[ ] 中,然后把这个指针后移一位(再次指向此序列中最小值),继续比较两指针指向的数值,然后放到数组res[ ] 中。循环往复重复此操作,直至排序成功。

(如果两个指针指向的数值相等,优先把第一个序列中的数值存到res中,这样能保证排序是稳定的

void merge_sort(int q[], int l, int r)
{
    if (l >= r) return;

    int mid = l + r >> 1;
    merge_sort(q, l, mid);
    merge_sort(q, mid + 1, r);

    int k = 0, i = l, j = mid + 1;
    while (i <= mid && j <= r)
        if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
        else tmp[k ++ ] = q[j ++ ];

    while (i <= mid) tmp[k ++ ] = q[i ++ ];
    while (j <= r) tmp[k ++ ] = q[j ++ ];

    for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}

时间复杂度

平均的快排 和 归并排序 的时间复杂度都是 nlog2n

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值