小菜鸟的算法学习笔记——快速排序

        快速排序在最坏情况下的时间复杂度为O(n2),但其期望时间复杂度是O(nlogn),且其中隐含的常数因子很小,固快速排序通常是实际排序应用中最好的选择。

        快速排序的思路如下:

        1、从A[p,r]中选出一个q,使得A[p,q-1]中的元素均小于A[q],A[q+1,r]中的元素均大于A[q];

        2、对A[p,q-1]及A[q+1,r]进行快速排序,如此递归。

        关键点在于如何选取其中的q,将该函数命名为partition(),其代码如下:

int partition(vector<int>& A, int p, int r)
{
	int i = p - 1;
	int x = A[r];
	for (int j = p; j < r; ++j)
	{
		if (A[j] <= x)
		{
			i = i + 1;
			int temp = A[j];
			A[j] = A[i];
			A[i] = temp;
		}
	}
	int temp = A[i + 1];
	A[i + 1] = A[r];
	A[r] = temp;

	return i + 1;
}

        记住以下几点前提:

        1、默认取A[r]为参照值,即为最后确定的A[q](最后将r位置的元素移动到q处);

        2、i元素是起到了分界线的作用,在i左边是比A[r]小的元素,在右边则反之。

        对A中的元素从p遍历到r-1,一旦遇到了比A[r]小的数,就需要将i往右移一格(因为i最初在p-1的位置),随后将这个比A[r]小的数与A[i]交换,这样就可以保证i元素的功能正常。当前期一直是比A[r]小的数时,就相当于同一个数与自身交换,所以i元素的作用也是正常的。当遇到比A[r]大的数时,跳过循环,进行下一个遍历。

        实现代码如下:

#include <iostream>
#include <string>
#include <vector>
using namespace std;


int partition(vector<int>& A, int p, int r)
{
	int i = p - 1;
	int x = A[r];
	for (int j = p; j < r; ++j)
	{
		if (A[j] <= x)
		{
			i = i + 1;
			int temp = A[j];
			A[j] = A[i];
			A[i] = temp;
		}
	}
	int temp = A[i + 1];
	A[i + 1] = A[r];
	A[r] = temp;

	return i + 1;
}



void quicksort(vector<int> &A,int p,int r)
{
	if (p < r)
	{
		int q;
		q = partition(A, p, r);
		quicksort(A, p, q - 1);
		quicksort(A, q + 1, r);
	}
}

int main()
{
	int num;
	cout << "输入子数组的元素数目" << endl;
	cin >> num;
	vector<int> vector_test(num);
	cout << "依次输入子数组的各元素" << endl;
	for (int i = 0; i < num; ++i)
	{
		cin >> vector_test[i];
	}
	cout << "以下是快速排序算法后的结果" << endl;
	quicksort(vector_test,0,num-1);
	for (int i = 0; i < vector_test.size(); ++i) { cout << vector_test[i] << endl; }
	return 0;
}

        前面提到,对于最坏情况,快速排序的时间复杂度跟插入排序一样。为了避免这种情况的发生,使快速排序的时间复杂度尽量接近期望值,需要引入随机化的功能。

        随机化体现在partition函数中选取的A[r]。因为在实际应用中,所有数据的排列并不是等概率的,很可能A[r]本身的选取就是最坏的情况。因此需要选用随机化函数,生成一个在p-r之间的随机数,将这个随机数所处位置的值与A[r]进行交换,将新的A[r]作为partition函数内部的参考值。这样便可实现算法的随机化。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值