算法中的精确时间计数器的应用

来源:互联网 发布:菜鸟也能数据分析 编辑:程序博客网 时间:2024/04/30 14:31

算法中的精确时间计数器的应用

流浪狗 2006.3

   评价一个算法的好坏,在运行时所消耗的时间是一个很重要的参数,可以反应出该算法的时间复杂度。要测试一个程序运行时所消耗的时间,我们可以写出很多种算法。很多编译器都提供了相关的时间函数库,还有系统的API等等。但是,我们会发现这些函数在程序中根本本能得到满意的结果。有时候设计得很好的算法,或者很小的算法,在运行的时候非常快,在1ms以内,这时候要测试这个算法所消耗的时间就是一件不容易的事情。

  在头文件time.h中有个函数clock(),返回clock_t的类型,可以通过两次调用clock函数,来确定时间间隔。API中有一个函数叫做GetTickCount的函数,可以得到当前计算机运行的时间,它返回一个DWORD值。在程序短之前加入一句DWORD t=GetTickCount();在程序段后加入t=GetTickCount()-t,则t的结果就是此程序段运行的时间。但是我们会发现很多程序段的结果输出都是0ms,所以我们需要比这个精度更高的函数。有没有这样的函数呢,通过查询MSDN,发现有两个函数满足要求,QueryPerformanceFrequency和QueryPerformanceCounter,它可以精确到0.5微秒,具体说明可以参见MSDN。为了方便我们以后在对算法时间的计算,我们把他封装成一个计时器类:

#include <windows.h>
#include<iostream.h>

using namespace std;

class TimeTake{
public:
 TimeTake():dCount(0)
 {
  // 获得计数器的时钟频率
  QueryPerformanceFrequency(&lPoint);
  dFreq=(double)lPoint.QuadPart;
 }
 ~TimeTake()
 {  
 }
 void print()
 {
  cout<<dCount<<" ms elapse in the  algothim!"<<endl;
 }
 void start()
 {
  //第一次取计数器的值
  QueryPerformanceCounter(&lPoint);
  lPart=lPoint.QuadPart;
 }
 void end()
 {
  //再一次取计数器的值并计算中间的时间间隔,表示成ms
  QueryPerformanceCounter(&lPoint);
  dCount=(double(lPoint.QuadPart-lPart)/dFreq)*1000;
 }
private:
 LARGE_INTEGER lPoint;
 LONGLONG lPart;
 double  dFreq, dCount; 
};

 我们可以写三个算法,用其对他们进行测试,下面几个算法都是求最大公约数的问题,第二个是第一个算法的改进,第三个是求使得a*m+b*n=d的最大公因数,详细算法如下:

DWORD mode1(DWORD m,DWORD n)
{
 int r=m%n;
 while(r!=0)
 {
  m=n;
  n=r;
  r=m%n;
 }
 return n;

}
DWORD mode2(DWORD m,DWORD n)
{
 DWORD r,result;
 while(1)
 {
  r=m%n;
  if(r==0)
  {
   result=n;
   break;
  }

  m=n%r;
  if(m==0)
  {
   result=r;
   break;
  }

  n=r%m;
  if(n==0)
  {
   result=m;
   break;
  }

 }
 return result;
}

//求接a,b使得am+bn=d,d为最大公倍数
DWORD mode(DWORD m,DWORD n,int& a,int& b)
{
 int al,bl; //求解al,bl使得al*m+bl*n=c;
 DWORD c,d,q,r,t;
 c=m;
 d=n;
 a=bl=0;
 b=al=1;
 while(1)
 {
  q=c/d;
  r=c%d;
  if(r==0)
   break;
  else
  {
   c=d; d=r;
   t=al;
   al=a;
   a=t-q*a;
   t=bl;
   bl=b;
   b=t-q*b;
  }
 }
 return d;

}

 然后编写主程序进行测试:

int _tmain(int argc, _TCHAR* argv[])


{

 TimeTake tk;
 int a,b;
 DWORD m,n,d1,d2;
 cout<<"please input m and n"<<endl;
 cin>>m>>n;
 while(n==0)
 {
  cout<<"n can't be zero,please input n again!"<<endl;
  cin>>n;
 }

 tk.start();
 d1=mode1(m,n);
 cout<<"the mode 1's result is "<<d1<<endl;
 tk.end();
 tk.print();

 tk.start();
 d2=mode2(m,n);
 cout<<"the mode 2's result is "<<d2<<endl;
 tk.end();
 tk.print();

 tk.start();
 d2=mode(m,n,a,b);
 cout<<"the result is "<<a;
 if(b>=0)
  cout<<"*m+"<<b<<"*n="<<d2<<endl;
 else
  cout<<"*m"<<b<<"*n="<<d2<<endl;
 tk.end();
 tk.print();

 return 0;
}

 输出结果如下:

please input m and n
150
456
the mode 1's result is 6
1.9469 ms elapse in the  algothim!
the mode 2's result is 6
1.23787 ms elapse in the  algothim!
the result is -3*m+1*n=6
1.18842 ms elapse in the  algothim!
Press any key to continue

通过多组数据的输入,我们可以肯定的是第二种算法比第一种算法用的时间少,因为第二种算法避免了第一种算法的重复赋值。但是第三种算法与前两种算法相比,体现出时间的不确定性,有时候时间处于前两种算法之间,有时候又比前两种都少。从表面上来看,第三种算法比前两种做的事情都要多,但是为什么他用的时间最少呢?

原创粉丝点击