快排两种实现及五种优化

快速排序是一个优秀的排序算法,O(n²)和Ω(nlgn),期望运行时间:θ(nlgn)且常数因子较小。

快排运用了分治的思想

分:将数组划分成两部分(核心,partition)

治:递归地对划分地两个子数组进行排序

合并:无需合并,因为快排是直接在数组内部进行元素交换的

 

以下给出Partition的几种实现方法和优化方法:

实现一(标准版)

①选取首元素或尾元素为主元(pivot)

②从前往后遍历,遇到不比自己大的元素就把它移到前面(同时把大的移到后面)

③将pivot与A[q]交换

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <ctime>
using namespace std;

void quickSort(int a[], int low, int high);

int a[10] = {5,2,1,5,6,3,9,0,3,8}; 

int main()
{
	srand(time(NULL));

	quickSort(a,0,9);

	for(int i=0; i<10; ++i)
		cout<<a[i]<<' ';

	return 0;
}

void quickSort(int a[], int low, int high)
{
    if(low >= high) return;
	int i = low - 1;
	int j = rand() % (high - low + 1) + low;
	swap(a[high], a[j]);
	int flag = a[high];

	for(int j = low; j < high; ++j)
		if(a[j] <= flag)
			swap(a[++i], a[j]);
	swap(a[++i], a[high]);

	quickSort(a, low, i-1);
	quickSort(a, i+1, high);
}

 

【实现二】(Hoare划分)

 

①分别从前面和后面开始遍历找到一个不比主元小的数a和b,交换a和b

②一直循环到整个数组被遍历

注:最后子数组A的元素全部小于等于子数组B的元素

 

【优化一】(随机化快排)

方法:随机选取元素与首(尾)元素交换,然后选取首(尾)元素为pivot

意义:加强随机性,使得其成为一个真正的随机化算法,即使在元素全部逆序的情况下也能保持Θ(nlgn)的速度

 

【优化二】(与插入排序结合)

方法:当n≤k(可能为500)时候,改用插入排序(O(n)~O(n²))

意义:减少递归的次数,且当数组"几乎有序"时,插入排序较快

 

【优化三】(针对元素值相同的快速排序)

方法:

①先把比pivot(A[1])小的放到前面(A[2...q])

②从q+1找和pivot相等的元素,跳过

③从数组尾向前遍历,将与pivot相等的元素转移到中间

意义:避免较多元素相等时导致复杂度骤增为θ(n²)

缺点:增加了比较的次数

pivot_t partition(int A[], int p, int r) {
    int x = A[r - 1],
        q = p,
        t,
        tmp;

    for (int i = p; i < r - 1; i++) {
        if (A[i] < x) {
            EXCHANGE(A[q], A[i]);
            q++;
        }
    }

    for (t = q; t < r && A[t] == x; t++);

    for (int i = r - 1; i >= t; i--) {
        if (A[i] == x) {
            EXCHANGE(A[t], A[i]);
            t++;
        }
    }

    pivot_t result = {q, t};
    return result;
}

 

【优化四】(尾递归技术)

 

方法:将对右数组的递归调用转化为一个循环结构

意义:(不太清楚,好像是减少下栈深度)

TAIL-RECURSIVE-QUICKSORT(A, p, r)
  while p < r
      // Partition and sort left subarray
      q = PARTITION(A, p, r)
      TAIL-RECURSIVE-QUICKSORT(A, p, q - 1)
      p = q + 1

 

【优化五】(三数取中划分)

方法:取三个数的中位数作为pivot

意义:增大"好的划分"的概率

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值