快速排序两种最基本思路

基本思想

快速排序是对冒泡排序的一种改进
基本思想:

  1. 通过一趟排序将要排序的数据分割成独立的两部分。
  2. 其中一部分的所有数据都比另外一部分的所有数据都要小。
  3. 然后再按此方法对这两部分数据分别进行快速排序,整个排序可以递归进行,一次整个数据变成有序序列
    注意:
    其主要运用了分治的思想
    有不同种方法将该段数据分成两段(小于等于key的一段在一边,大于key的一段在一边,key的数据在这两段段中间)
    快排一次只能把一个数排好,放在正确的位置。
    key可以选最左边的数,此时先移动右边的数j,
    key也可以选最右边的数,此时先移动左边的数i
    快速排序主要有两种方法,一种是标准算法,另一种是两头交换法,基本思想是一样的,但有些细节上有所不同。

方法一:两头交换法

过程图解:

首先我们选取最左边的数为标准数key,再设最左边的数为i,设最右边的数为j.注意此时从右边开始移动。
key = 6
在这里插入图片描述
j从右向左移动直到找到比key小的那个数停下
i从左往右移动直到找到比key大的数停下。
交换它们两个。
在这里插入图片描述
6 1 2 5 9 3 4 7 10 8

ij
61259347108

key = 6
继续进行上面的操作,
j从右向左移动直到找到比key小的那个数停下
i从左往右移动直到找到比key大的数停下。
然后交换它们两个。
在这里插入图片描述
6 1 2 5 4 3 9 7 10 8

ij
61254397108

最终j找到比key小的数停下
i继续向前寻找时与j相遇。
此时交换这个数与key的位置。
在这里插入图片描述
3 1 2 5 4 6 9 7 10 8
可以看出来key此时所处的位置,前面都是比key小的,后面都是比key大的。所以这里就是key的位置
然后分别对6前半段和后半段进行上面的排列
在这里插入图片描述
最终排序完成。

代码实现:

int a[100];
void quicksort(int left, int right);
int main() {
    int n;
    scanf("%d",&n);
    for(int i = 0; i < n; i++) {
        scanf("%d ",&a[i]);
    }
    quicksort(0, n-1);
    for(int i = 0; i < n; i++) {
        printf("%d ",a[i]);
    }
    return 0;
}
void quicksort(int left, int right) {
    int i, j, t;
    
    if(left > right) {
        return ;
    }
    int key = a[left];
    i = left;
    j = right;
    while ( i != j) {
        while (a[j] >= key && i < j) {
            j--;
        }
        while (a[i] <= key && i < j) {
            i++;
        }
        if(i < j) {
            t = a[i];
            a[i] = a[j];
            a[j] = t;
        }
    }
    
    a[left] = a[i];
    a[i] = key;
    quicksort(left, i-1);
    quicksort(i+1, right);
}

方法二:标准算法(填坑法)

优化不必要的交换,直接进行替换操作,不进行交换。
key=23
第一步,i=0, j=8.选取基准数key为23.
可以想象成i = 0那个位置有一个坑,标记为*
j开始向左移动。

012345678
2315378922143956
i=0<-- j=8
*

第二步:
从j向左寻找比key小的数,找到后填入坑中,此时j所在的位置就变成坑了。
i开始向右移动

012345678
915378922143956
i=0 -->j=7
*

下一步:
i从左往右移动,寻找比key大的数,找到后填入坑中,并且i此时所在的位置就变成了坑。
j开始向右移动。

012345678
9153789221433756
i=2<-- j=7
*

下一步:
j从右往左移动,寻找比key小的数,找到后填入坑中,并且j此时所在的位置就变成了坑。
i开始向右移动。

012345678
9152189221433756
i=2 -->j=5
*

下一步:
i从左往右移动,寻找比key大的数,找到后填入坑中,并且i此时所在的位置就变成了坑。
j开始向左移动。

012345678
9152189289433756
i=3<-- j=5
*

下一步:
j从右往左移动,寻找比key小的数,找到后填入坑中,并且j此时所在的位置就变成了坑。
i开始向左移动。

012345678
915212289433756
i=3 -->j=4
*

i向右移动,此时与j相遇 i = j = 4.

012345678
915212289433756
i = j=4
*
012345678
9152122389433756
key
*

此时key 23所在的位置就是它在排列中应该在的位置。前面的数都是比他小的数,后面都是比它大的数。
最后我们对以上的操作进行分治,即分别对23前面的数列和后面的数列进行上面的操作排序。
在这里插入图片描述

最终排序完成。

代码实现:

#include<stdio.h>
int a[100];
void quicksort(int a[], int low, int high) {
    int i = low;
    int j = high;
    int key = a[low];
    while (i < j) {
        while (i < j && a[j] >= key) {
            j--;
        }
        if( i < j) {
            a[i] = a[j];
        }
        while (i < j && a[i] < key) {
            i++;
        }
        if( i < j) {
            a[j] = a[i];
        }
    }
    a[i] = key;
    if(low < i) quicksort(a, low, i-1);
    if(high >i) quicksort(a, i+1, high);
}

int main() {
    int n;
    scanf("%d",&n);
    for(int i = 0; i < n; i++) {
        scanf("%d ",&a[i]);
    }
    quicksort(a, 0,  n-1);
    for(int i = 0; i < n; i++) {
        printf("%d ",a[i]);
    }
    return 0;
}
  • 10
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值