舍伍德算法 线性时间选择

 记录一下      算法分析实验七   

利用Sherwood型随机化思路求解线性时间选择算法,并计算出程序运行所需要的时间。

① 参考课件、教材、其它资料,将伪代码改成正式程序代码。

② 用一组小数据,手工验证程序正确性,发现可能的错误并修复。

③ 自己设计代码,生成小、中、大规模数据,分别存到三个.txt文件。

④ 对三种规模的数据,检测程序运行时间,观察并记录结果和发现。

 

先贴一下用来生成随机数文本的代码:

/*
#include <iostream>
#include <fstream>
#include <stdlib.h>
 
using namespace std;
 
int main()
{
  fstream fso("50000.txt", ios::out);
   
  int i;
  for(i = 0; i < 50000; ++i)
    fso << rand() << ' ';
  fso.close();
   
  fstream fsi("50000.txt", ios::in);
  int x[50000];
  for(i = 0; i < 50000; ++i)
    fsi >> x[i];
   
  for(i = 0; i < 50000; ++i)
    cout << x[i] << '\t';
     
  return 0;
}
*/ 

//万级以下用这个缩小范围(四舍五入生成整数)
 
#include<iostream>
#include<stdlib.h>
#include <fstream>
#include<time.h>
#include<iomanip>
#include<stdio.h>
#include<math.h>
using namespace std;
 
double round(double r)
{
    return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}

double randomRange(double a, double b)
{   
    double x = (double)rand() / RAND_MAX;
    double result = x*(b - a) + a;
    return round(result);
}
 
 
int main() {   
    srand((int)time(0));
   fstream fso("10.txt", ios::out);
   int i;
   for(i = 0; i <10; ++i)
       fso <<randomRange(0, 100)<< ' ';   // 
    fso.close(); 
    
    fstream fsi("10.txt", ios::in);
    int x[10];
    for(i = 0; i <10; i++)
        fsi >> x[i]; 
        
    for ( i = 0; i <10; i++) {      
        cout << randomRange(0, 100) << " ";
    }
    cout << endl;
 
    system("pause");
}

主体代码:

#include<time.h>
#include<stdio.h>
#include<math.h>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;

template<class Type>  
Type select(Type a[],int l,int r,int k);  
  
template<class Type>  //是否越界 
Type select(Type a[],int n,int k);  
  
template<class Type>  
void Shuffle(Type a[],int n);  
  
template <class Type>  
inline void Swap(Type &a,Type &b);  
  

int main()
{
	  int n,k,i;
	  cout<<"输入三种数据选择元素规模:1.10;2.500;3.50000"<<endl;
	  cin>>n;
	  int *a=new int[n+1];
	  cout<<"求第k小个元素,请输入k:"<<endl;
	  cin>>k; 
	  if(n==10)
	  {
	  	  fstream fsi("10.txt", ios::in);
	  	  for(i = 0; i < 10; ++i)
               fsi >> a[i];
   
          for(i = 0; i <10; ++i)
             cout << a[i] << '\t';
	  }
	  else if(n==500)
	  {
	  	  fstream fsi("500.txt", ios::in);
	  	  for(i = 0; i < 500; ++i)
               fsi >> a[i];
   
          for(i = 0; i <500; ++i)
             cout << a[i] << '\t';	  	
	  }
	  else if(n==50000)
	  {
	  	  fstream fsi("50000.txt", ios::in);
	  	  for(i = 0; i < 50000; ++i)
               fsi >> a[i];
   
          for(i = 0; i <50000; ++i)
             cout << a[i] << '\t';	  	
	  }
	  cout<<endl;
	  Shuffle(a,n);
	  cout<<"数组洗牌后:"<<endl;
	  for(i=0;i<n;i++)
	      cout<<a[i]<< '\t'; 
	  cout<<endl;
	   
    clock_t start,end,over;
    start=clock();
    end=clock();
    over=end-start;
    start=clock();
      cout<<"数组第k小元素为:"<<select(a,n,k)<<endl;
	end=clock();
	printf("The time is %6.3f",(double)(end-start-over)/CLK_TCK);    
     cout<<endl;
      system("pause");
      return 0;
}

//计算a[0:n-1]中第k小元素  
//假设a[n]是一个键值无穷大的元素  
template<class Type>  
Type select(Type a[],int n,int k)  
{  
    if(k<1 || k>n)  
    {  
        cout<<"请输入正确的k!"<<endl;  
        return 0;  
    }  
    return select(a,0,n-1,k);  //合法 
}  
  
//计算a[l:r]中第k小元素  
template<class Type>  
Type select(Type a[],int l,int r,int k)  
{  
    while(true)  
    {  
        if(l>=r)  //数组仅1元素 
        {  
            return a[l];  
        }  
        int i = l;  
        int j = r+1;  
        Type pivot = a[l];  //轴值=最左边元素 
  
        //以划分基准为轴做元素交换 
		//小于轴值的换到左边,大于轴值的换到右边 
        while(true) 
        {  
            while(a[++i]<pivot);  
            while(a[--j]>pivot);  
            if(i>=j)  
            {  
                break;  
            }  
            Swap(a[i],a[j]);    
        }  
  
        if(j-l+1 == k)//第k小找到,是轴值  
        {  
            return pivot;  
        }  
        //如果没找到(轴值不是第k小) 
        //a[j]必然小于pivot,做最后一次交换,满足左侧比pivot小,右侧比pivot大  
        a[l] = a[j];  
        a[j] = pivot;  
  
        //对子数组重复划分过程  
        if(j-l+1<k)  //第k小在轴值右边 
        {  
            k = k-j+l-1;//右侧:k-(j-l+1)=k-j+l-1  
            l = j + 1;  
        }  
        else  //第k小在轴值左边 
        {  
            r = j - 1;  
        }  
    }  
}  

template <class Type>  
inline void Swap(Type &a,Type &b)  
{  
    Type temp = a;  
    a = b;  
    b = temp;  
}  
/*
//随机洗牌算法  
template<class Type>  
void Shuffle(Type a[],int n)  
{  
    static Randomnumber rnd; //随机数类 
    for(int i=0; i<n; i++)  
    {  
        int j = rnd.Random(n-i)+i; //随机生成i~n之间的整数 
        Swap(a[i],a[j]);  //随机选取的数作为基准值 
    }  
}    
*/

//随机洗牌算法  
template<class Type>  
void Shuffle(Type a[],int n)  
{  
    srand((int)time(0));
    double x,r;
    for(int i=0; i<n; i++)  
    {  
       x = (double)rand() / RAND_MAX;
       r = x*(n - i) + i;
      (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
    
        int j = (int)r; //随机生成i~n之间的整数 
        Swap(a[i],a[j]);  //随机选取的数作为基准值 
    }  
}    
不想用随机数类所以直接生成i~n随机数,运行起来似乎没有问题的样子。
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值