Randomized Algorithm 随机算法 和 随机快速排序例子

随机算法

随机算法听起来是很高级的内容了,但是,其实随机算法是很简单的内容,很好理解的。

随机算法对于一个问题也许不是准确的解法,而且对于同一个输入,也许每次运行也会产生不同的结果。

随机算法可以在运行的时候,利用一个数据流,在其中做随机选择。

相对比一般的算法(e.g.deterministic algorithm),主要有两个优点:

1 运行时间和空间都比一般的我们现在知道的最优算法都要好(the best deterministic algorithm)

2. 更加容易理解,且容易实现

例子1:

我们要求验证F(x1,x2,……xn)这个函数是否是等于0.如果按照一般算法分析的话,那么如果数量大的话,用超级计算机也不一定能搞定,但是我们随机产生几组x1,x2...xn值,然后代入验证,如果有一次是不等于零的,那么这个函数就不等于零了,如果代入10次值还是等于零的话,就可以说函数恒为零。

有一定几率这个结果是不正确的,但是这个几率非常非常低,可以忽略不计了。

这个看起来是很高级的算法,其实思想是很简单的吧。

随机算法可以分为两大类:

1 Las Vegas算法:

这个算法总是能产生正确的结果,否则就不会返回结果。

2 Monte Carlo算法:

总是会返回结果,但是结果不一定是正确的。但是出现不正确的答案的几率可以非常非常低,而且我们可以多次运行,每次做不同的随机选择,那么几率就更加低了。

随机算法的效率:比如一般算法的效率是O(n),那么随机算法可以是O(1),我们只选择一个实例来验证就可以了,比如前面的列子。当然我们也可以根据我们的需要选择多个实例m。那么效率就是O(m)。这个m要比n少很多。那么效率就高很多了。

例子2:

如我们都比较熟悉的快速排序,平均效率是O(nlgn),但是最坏效率是O(n*n);

快速排序可以参考这里:http://blog.csdn.net/kenden23/article/details/14643823

最坏情况就是出现在这个数量原来就是排好序的。那么如何尽量避免这种情况出现呢?

就是在选择数轴的时候,随机的选择一个数,而不是固定的选择一个数。这样主要不一样就是:这个数的选择不依赖于原数列了。最大可能地保证了不会出现最坏情况。

下面我们看看如何写这个随机算法(算法包含了随机和非随机算法比较):

#include<iostream>
#include<vector>
#include<cstdlib>
#include<ctime>

using namespace std;

//C++'s array range should be [low, up], the same as [low, up+1)
int partition(vector<int> &vi, int low, int up)
{
	int pivot = vi[up];
	int i = low-1;
	for (int j = low; j < up; j++)
	{
		if(vi[j] <= pivot)
		{
			i++;
			swap(vi[i], vi[j]);
		}
	}
	swap(vi[i+1], vi[up]);
	return i+1;
}

int randomizedPartition(vector<int> &vi, int low, int up)
{
	int i = rand() % (up-low) + low;
	swap(vi[i], vi[up]);
	return partition(vi, low, up);
}


//C++'s array range should be [low, up], the same as [low, up+1)
void quickSort(vector<int> &vi, int low, int up)
{
	if(low < up)
	{
		int mid = partition(vi, low, up);
		//Watch out! The mid position is on the place, so we don't need to consider it again.
		//That's why below is mid-1, not mid! Otherwise it will occur overflow error!!!
		quickSort(vi, low, mid-1);
		quickSort(vi, mid+1, up);
	}
}

void randomizedQuickSort(vector<int> &vi, int low, int up)
{
	if(low<up)
	{
		int mid = randomizedPartition(vi, low, up);
		randomizedQuickSort(vi, low, mid-1);
		randomizedQuickSort(vi, mid+1, up);
	}
}

void qSort(vector<int> &vi)
{
	quickSort(vi, 0, vi.size()-1);
}

void qSort(vector<int> &vi, int low, int up)
{
	quickSort(vi, low, up-1);
}
void randomizedQSort(vector<int> &vi)
{
	randomizedQuickSort(vi, 0, vi.size() - 1);
}

void randomizedQSort(vector<int> &vi, int low, int up)
{
	randomizedQuickSort(vi, low, up-1);
}

int main()
{
	int a[] = {3,5,7,9,2,3,1,0,7,5,4};
	vector<int> va(a, a+11);
	int b[] = {31,25,37,49,52,63,71,20,87,95,34};
	vector<int> vb(b, b+11);

	cout<<"Before quicksort:\n";
	for(auto x:va)
		cout<<x<<" ";
	cout<<endl;

	QSort(va);

	cout<<"After quicksort:\n";
	for(auto x:va)
		cout<<x<<" ";
	cout<<endl;
	
	srand(time(NULL));

	cout<<"Before randomized quick sort:\n";
	for(auto x:vb)
		cout<<x<<" ";
	cout<<endl;

	randomizedQSort(vb);

	cout<<"After randomized quick sort:\n";
	for(auto x:vb)
		cout<<x<<" ";
	cout<<endl;
	
	cout<<endl;
	system("pause");
	return 0;
}


输出结果:

如果您觉得这样出现最坏情况的概率还不够小,那么可以进一步改进,使用三个随机数,然后用三个随机数的中间数来作为新的中轴数值,程序如下:

int median(int a, int b, int c)
{
	if (a>b && a<c || a>c && a<b) return a;
	else if (b>a && b<c || b>c && b<a) return b;
	else return c;
}

int medianRandPartition(vector<int> &vi, int low, int up)
{
	int a = rand() % (up-low) + low;
	int b = rand() % (up-low) + low;
	int c = rand() % (up-low) + low;
	int i = median(a, b, c);
	swap(vi[i], vi[up]);
	return partition(vi, low, up);
}

void medianRandQuickSort(vector<int> &vi, int low, int up)
{
	if(low<up)
	{
		int mid = medianRandPartition(vi, low, up);
		medianRandQuickSort(vi, low, mid-1);
		medianRandQuickSort(vi, mid+1, up);
	}
}

void medianRandQSort(vector<int> &vi)
{
	medianRandQuickSort(vi, 0, vi.size() - 1);
}

void medianRandQSort(vector<int> &vi, int low, int up)
{
	medianRandQuickSort(vi, low, up-1);
}


顺便提一下,Quick sort其实可以不用两个递归函数,使用一个如下:

void tailQuickSort(vector<int> &vi, int low, int up)
{
	while (low < up)
	{
		int mid = partition(vi, low, up);
		tailQuickSort(vi, low, mid-1);
		low = mid+1;
	}
}


一般应用使用一般的快速排序就可以了,但是到了某些特殊应用或者高级应用随机算法就显得非常有用了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值