分治法例子

找最大元和次大元

算法描述:
将问题拆分成子问题,比较一个或者两个元素,一个元素时,最大值次大值是本身,两个元素时,最大值是较大的一个,次大值是小的。如果不是最小情况,再将问题拆分成小问题。最后传回来前面最大值次大值和后面一段最大值次大值,比较这四个数,如果后面最大值比最大值大,最大值为max1,再比较次大值,大的给次大值。这题关键在于如何比较两次的最大值和次大值。
源程序:

#include <iostream>
using namespace std;
int a[100];

/*求最大值和次大值*/
void Max12(int i,int j,int &max,int &mimax){
	int max1,mimax1;
	if(i==j){//一个元素时,最大值次大值是本身
		max=mimax=a[i];
	}
	else if(i==j-1){//两个元素时,最大值是较大的一个,次大值是小的
		if(a[i]<a[j]){
			max=a[j];mimax=a[i];
		}
		else{
			max=a[i];mimax=a[j];
		}
	}

	else{//其他情况时调用Max12,将问题分解
		int m=(i+j)/2;
		Max12(i,m,max,mimax);
		Max12(m+1,j,max1,mimax1);

		if(max1>max){//如果后面最大值比最大值大,改变最大值次大值
			mimax=max;
			max=max1;
			if(mimax1>mimax)
				mimax=mimax1;
		}
		else if(max1>mimax){//后面最大值大于次大值,改变次大值
			mimax=max1;
		}
	}
}

int main(){
	int n,i;
	int max,mimax;
	cin>>n;
	for(i=0;i<n;i++)
		cin>>a[i];

	max=a[0];//给最大值次大值初始化
	mimax=a[0];

	Max12(0,n-1,max,mimax);
	cout<<max<<" "<<mimax<<endl;
	return 0;
}

快速排序

算法描述:
用快速排序使所给序列从大到小排序,在写快速排序前要写划分函数。划分函数能把比第一个值大的放到左边,小的放到右边。这里设置了个监视哨,把序列结尾赋值为无穷小,防止i越界。i往后走,直到找到比第一个值小的停止,j往前走直到找到比第一个值大的停止,如果i,j没有交错,交换两个元素,直到,i,j交错。最后把j的值和第一个值交换,第一个值就排好了顺序。

源程序:

#include <iostream>
using namespace std;
int a[100];

/*从大到小划分函数*/
int Pa(int left,int right){
	int i=left;
	int j=right+1;
	int temp=a[j];//暂时保留right后面的元素,并把他的值变为无穷大
	a[j]=0x80000000;
	do{
		do
			i++;
		while(a[i]>a[left]);//i找比第一个值小的

		do
			j--;
		while(a[j]<a[left]);//j找比第一个值大的

		if(i<j)
			swap(a[i],a[j]);//把大的和小的交换位置
	}while(i<j);

	swap(a[left],a[j]);
	a[right+1]=temp;
	return j;
}

/*快速排序*/
void QuickSort(int left,int right){
	if(left<right){
		int j=Pa(left,right);
		QuickSort(left,j-1);
		QuickSort(j+1,right);
	}
}

int main(){
	int i,n;
	cin>>n;
	for(i=0;i<n;i++){
		cin>>a[i];
	}
	a[n]=0x80000000;//最后为无穷大,当做监视哨
	QuickSort(0,n-1);
	for(i=0;i<n;i++){
		cout<<a[i]<<" ";
	}
	cout<<endl;
	return 0;
}

查找第k小元素

算法描述:
找第k小的元素,利用patition划分函数,没找一次就能找到第j+1小的,利用这点就一直调用划分函数直到找到第K小的,这里注意一点就是比较j和k大小来减少调用次序,类似折半查找,当j大时,找j 左边的,小时,找右边的,直到找到。

源程序:

#include <iostream>
using namespace std;
int a[100];

/*从小到大划分函数*/
int Pa(int left,int right){
	int i=left;
	int j=right+1;
	int temp=a[j];
	a[j]=0x7fffffff;
	do{
		do
			i++;
		while(a[i]<a[left]);

		do
			j--;
		while(a[j]>a[left]);

		if(i<j)
			swap(a[i],a[j]);
	}while(i<j);
	swap(a[left],a[j]);
	a[right+1]=temp;
	return j;
}

/*这是找到第k小的元素位置*/
int find(int left,int right,int k){
	int j;
	j=Pa(left,right);
	do
	{
		if(j>k)//如果j是大的,K小肯定在左边
			j=Pa(left,j-1);
		else if(j<k)//j大,k小在右边
			j=Pa(j+1,right);
	}while(j!=k);//循环直到找到第k小
	return j;
	
}

int main(){
	int n,i,j;
	int x;
	cin>>n;
	for(i=0;i<n;i++){
		cin>>a[i];
	}
	cin>>x;
	j=find(0,n-1,x-1);//x-1是为了适应数组下标
	cout<<a[x-1]<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/jihome/article/details/94966165