素数算法的优化之路

素数算法的优化之路素数算法的优化之路

大家好,又见面了,我是你们的朋友全栈君。一、素数的定义


        质数又称素数。指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数(不包括0)整除的数。因为合数是由若干个质数相乘而得来的,所以,没有质数就没有合数,由此可见质数在数论中有着很重要的地位。


        比如:2,3,5,7,9…..都是素数。


 


二、构造素数算法


     写算法之前,先来说说以下这个东西:
     
     对于任意一个合数n,如果它有两个质因子x,y,显然n = x*y, 
     所以,由不等式性质可得,x <= sqrt(n), 即 x <= n^(1/2)。
     
     推广一下,对于任意一个合数,如果它有k个质因子x1,x2,x3,…. ,xk,显然n = x1 * x2 * x3 * …. * xk,
     所以,由不等式性质可得, x <= n^(1/k),即每个质因子必小于或者等于n开k次方,其中x 属于集合{ 

x1,x2,x3,…. ,xk 
}。

    定义一个全局变量和一个全局数组,要是数组是分配在栈上的话,是有容量限制的,所以我们就定义个全局的。

     const unsigned int N = 50000;
     bool flag[N+1];


 

  
  1、算法一:按照定义,即可快速写出一个简单的构造素数算法
 


    

void PrimeCreateCommon()//按照定义
{
	for ( unsigned int i = 2; i <= N; ++i )
	{
		//由前面的铺垫,这里不难理解吧。因为我不知道这个数有几个质因子,
		//我就假设它只有两个,范围拉大一些,这个数的所有质因子都小于或
		//等于sqrt( (double)i ) + 1。其它的约数,必然是这些质因子的倍数
		//而已所以就没必要继续除下去了。
		bool flag = true;
		for ( unsigned int j = 2; j <= sqrt((double)i)+1; ++j )  
		{                              
			if ( i % j == 0 )         
			{                        
				flag = false;
			}
		}
		//if ( flag )
		//{
		// 	cout << i << " "; 
		//}
	}
	cout << endl;
}




   分析:该算法的时间复杂度为O(n*sqrt(n) ),在n比较大时(比如n = 50000),我的机器跑了个二十来秒,就也叫算法,呵呵,所以接下来我们来看另一种算法 ,那就是
古希腊数学家的埃拉托色尼给出的一个比较省力的算法——埃拉托色尼筛法
 




   2、算法二:筛选法

 


    首先,列出从2开始的数。然后,将2记在素数列表上,再划去所有2的倍数。根据定义,剩下的最小的数——在这里是3——必定是素数。将这个数记在素数列表上,再划去所有它的倍数,这样又会剩下一些数,取其中最小的,如此反复操作。最后剩下的都是素数。
   

void PrimeCreateExt()//筛选法优化
{
	memset( flag, 0, (N+1)*sizeof(bool) );
	for ( unsigned int i = 2; i <= sqrt(double(N)) + 1; ++i )
	{
		if ( !flag[i] )
		{
			for ( unsigned int j = 2*i; j <= N; j += i )
			{
				flag[j] = true;
			}
		}

	}

// 	for ( int i = 2; i <= N; ++i )
// 	{
// 		if ( !flag[i] )
// 		{
// 			cout << i << " ";
// 		}
// 	}
// 	cout << endl;
} 


 三、两种算法的运行时间对比
    
  

//测试函数
int main()
{
	clock_t start, finish;
	double duration = 0.0;

	cout << "筛选算法产生素数:" << endl;
	start = clock();
	PrimeCreateExt();
	finish = clock();
	duration = (double)(finish-start);
	cout << "时间消耗:" << duration << "ms" << endl << endl;

	cout << "普通算法产生素数:" << endl; 
	start = clock();
	PrimeCreateCommon();
	finish = clock();
	duration = (double)(finish-start);
	cout << "时间消耗:" << duration << "ms" << endl << endl; 
} 

   

 //产生50万以内的素数运行时间对比 

素数算法的优化之路

 四、空间上的优化
            略


作者:山丘儿
转载请标明出处,谢谢。原文地址:http://blog.csdn.net/s634772208/article/details/46327281

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/151674.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • efishell无法开机shell_开机出现efi shell卡住不动了解决方法全集「建议收藏」

    efishell无法开机shell_开机出现efi shell卡住不动了解决方法全集「建议收藏」[文章导读]最近有很多网友问我,为什么我的电脑开机后出现efishell提示进不了系统,开机出现efishell提示时,一般是由于第一启动项设置的是efishell启动的,有的网友告诉我,我第一启动项明明设置的是硬盘启动,当然还有一种情况就是前面的启动项都无法加载,然后按启动顺序启动,然后就启动到efishell了,出现这种情况一般就是系统引导破坏或是找不到引导项了。那么怎么找到原并解决…

    2022年7月24日
    6
  • Hadoop、Yarn和vcpu资源的配置

    Hadoop、Yarn和vcpu资源的配置

    2022年3月13日
    61
  • 匈牙利命名法

    匈牙利命名法

    2021年12月13日
    45
  • hibernate 二级缓存「建议收藏」

    hibernate 二级缓存「建议收藏」Hibernate缓存缓存(Cache):计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能。缓存中的数据是数据存储源中数据的拷贝。缓存的物理介质通常是内存Hibernate中提供了两个级别的缓存

    2022年5月24日
    34
  • Adapter的notifyDataSetChanged()

    Adapter的notifyDataSetChanged()notifyDataSetInvalidated(),会重绘控件(还原到初始状态)notifyDataSetChanged(),重绘当前可见区域publicvoidnotifyDataSetChanged():该方法内部实现了在每个观察者上面调用onChanged事件。每当发现数据集有改变的情况,或者读取到数据的新状态时,就会调用此方法。 publicvoidnoti

    2022年6月22日
    25
  • 购物程序「建议收藏」

    购物程序「建议收藏」#-*-coding:utf-8-*-"""CreatedonTueSep1116:35:292018@author:车路历程"&

    2022年8月3日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号