排序算法-快速排序

简介:

快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
快排同冒泡都属于交换排序。不同的是,冒泡排序一次只能消除一个逆序对,而快排一次可以消除多个。

图解:

在这里插入图片描述

实现思路 A:

通过上图可以发现,我们通过寻找一个轴点(上图为5)使轴点两侧满足:左侧不大于轴点,右侧不小于轴点。通过分治,可以使序列中任意一点都满足上述要求。大致思路如下。

  1. 寻找轴点
  2. 划分序列,再次寻找轴点,直至到达单个序列(单个数值有序)
寻找轴点步骤:
  1. 随机的在序列中选取一个数m,同序列最左侧(low)值替换,从而空出low位置
  2. 从两个方向遍历序列(low -> hight,hight - > low)
  3. 若low指向的值小于m,则low右移。否则将low指向的值交换
  4. 另一个方向,操作相反

关于上述值交换:因为lo(以下low简称lo,height简称hi)位置已空出。则我们可以先从hi方向左移遍历。若遇到小于m的情况,则将当前值移到 lo 位置(此时hi指向的位置已空出)。然后从lo方向右移遍历。若遇到大于m的情况,则将当前值移到 hi 位置。重复此过程,直至 lo = hi。

代码示例:
#include<bits/stdc++.h>
using namespace std;

int partition(int *n, int lo, int hi){
 	swap(n[lo], n[lo + rand()%(hi - lo + 1)]);
 	int m = n[lo];
 	while(lo < hi){
  		while((lo < hi) && (n[hi] >= m))
   			hi--;
  		n[lo] = n[hi];
  		while((lo < hi) && (n[lo] <= m))
   			lo++;
  		n[hi] = n[lo];
 	}
 	n[lo] = m;
 	return lo;
}

void quick_sort(int *n, int lo, int hi){
 	if(lo >= hi) return;
 	int mi = partition(n, lo, hi);
 	quick_sort(n, lo, mi);
 	quick_sort(n, mi + 1, hi);
}

int main(){
 	int len = 5;
 	int n[len];
 	for(int i = 0; i < len; i++)
  		cin >> n[i];
 	quick_sort(n, 0, len - 1);
 	for(int i = 0; i < len; i++)
  		cout << n[i] << " ";
 	return 0;
}
实现思路 B:

思路B类似思路A,只不过构建轴点的方法不同而已。思路B每次选取序列第一个元素作为轴点,通过快排方法不断使左侧小于轴点,右侧大于轴点。

代码示例:
int partation(int *n, int lo, int hi){
 	int i = lo, j = hi, m = n[lo];
 	while(i < j){
  		while(i < j && n[j] >= m)
   			j--;
  		if(i < j) 
   			swap(n[i++], n[j]);
  		while(i < j && n[i] <= m)
   			i++;
  		if(i < j)
   			swap(n[i], n[j--]);
 	}
	return i;
}

类似还有三点选取法等,其目的都是找到合适的轴点。从而提高快排效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值