素数算法的优化之路

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

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


        质数又称素数。指在一个大于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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 我现在A函数开启事务,然后调用B函数,B函数中也开启了事务

    我现在A函数开启事务,然后调用B函数,B函数中也开启了事务

    2022年2月8日
    43
  • pycharm打开闪退_手机微信闪退怎么回事

    pycharm打开闪退_手机微信闪退怎么回事我清了浏览记录也没用感觉这2个方法靠谱点,还没用过设置里面:选择高级-时间限然后开始清理或者设置面板中点高级-重置并清理或者重启https://jingyan.baidu.com/article/eb9f7b6dbfa6f6c79264e844.html…

    2022年8月27日
    2
  • Java8函数式编程

    最近使用lambda表达式,感觉使用起来非常舒服,箭头函数极大增强了代码的表达能力。于是决心花点时间深入地去研究一下java8的函数式。(想自学习编程的小伙伴请搜索圈T社区,更多行业相关资讯更有行业相关免费视频教程。完全免费哦!)一、lambda表达式先po一个最经典的例子——线程publicstaticvoidmain(String[]args){//Java7n…

    2022年4月1日
    31
  • (c语言)选择排序法和冒泡排序法

    (c语言)选择排序法和冒泡排序法问题描述:给定一个数组(或者输入一个数组),分别运用选择排序法和冒泡排序法将所要的结果输出。程序分析:                    选择排序1>.对于选择排序,首先理解排序的思想。给定一个数组,这种思想首先假定数组的首元素为最大(最小)的。此时就要利用3个变量i,j,k表示元素的下标。i表示当前,j表示找到的最大(最小)的下标,k用

    2022年6月25日
    22
  • SSL协议概述和握手过程

    SSL协议概述和握手过程SSL协议主要是为了保证WEB通信的安全性,是基于TCP协议的SSL协议有三个特性:1.机密性SSL协议的机密性主要依靠的是对称加密体质,在通信过程中,使用对称密码进行加密解密保证信息的安全性。2.完整性SSL协议的完整性主要依靠的是散列技术,对分组数据进行压缩之后,利用散列函数获得哈希值,加在分组信息的尾部,并且利用对称密码进行加密之后再传输(在传输到TCP层之前还有一个动作

    2022年5月25日
    42
  • Java中Scanner类的使用方法(小白专属)

    Java中Scanner类的使用方法(小白专属)一、Scanner类简介Java5新引入了java.util.Scanner类,主要用于扫描用户从控制台输入文本的程序。即当用户需要输入数据时,调用java.util包中的Scanner类,Scanner类能获取用户所输入的数据。二、如何使用Scanner类?(按步骤)先导入java.util.Scanner包;创建Scanner类的对象(基本语法)创建一个变量用于接收输入的数据,通过调用Scanner类的对象scanner来调用Scanner类中的next方法(控制台将等待

    2022年7月7日
    21

发表回复

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

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