找最大元和次大元
算法描述:
将问题拆分成子问题,比较一个或者两个元素,一个元素时,最大值次大值是本身,两个元素时,最大值是较大的一个,次大值是小的。如果不是最小情况,再将问题拆分成小问题。最后传回来前面最大值次大值和后面一段最大值次大值,比较这四个数,如果后面最大值比最大值大,最大值为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;
}