选择显示字体大小

c#算法设计与分析-寻找素数

    在这篇文章中,我将使用c#编制两个寻找素数的算法,说明算法设计的重要性以及算法的分析。

       素数寻找问题由来已久,一直是一些数学家追求的目的。关于素数的定义及性质,我就不在这里多叙了,相信大家都对此了如指掌。素数的寻找思路比较的简单,根据素数的性质(素数应该不能被除了1和它自身的其他数整除)我们可以从最小的素数2开始,一直到比它小1的数为止,用这些数去整除它,如果它能被整除则它必定不是素数,这是判断单个素数的方法(这个算法思想最简单,时间复杂度最大)。对于寻找比某一个给定的整数值小的所有素数也可以采用这种方法,不过我们会发现,采用这种单个判断的方法所耗的时间比较多。比如查找不大于10的素数,我们必须从2开始一个个判断,共需判断9个数,事实上按照我们后面讲述的方法,只需循环2次就可以了。因此,下面的两种方法都将基于删除法来做。

       我们来看看删除法的思想:

1.  将小于给定整数值n的所有正整数加到一个数组中;

2.  删除能够被一些整数整除的数;

3.  数组中遗留的元素就是最后要得到的素数序列。

对于第二步,我们将给出两种方法来实现。我们先来看看算法:

算法一:

class prime

     {

         public static int[] primelist;

         public  static void findprime(int n)

         {

              int[] intlist;

              intlist=new int[n];             

              for (int p=2;p<=n;p++) intlist[p-1]=p;

              for (int p=2;p<math.sqrt(n);p++)

              {

                   int j=p+1;

                   while (j<=n)

                   {

                       if ((intlist[j-1]!=0 ) && ((intlist[j-1]&#37; p)==0) ) intlist[j-1]=0;

                       j=j+1;

                   }

              }

              int i=0;

              for (int p=2;p<=n;p++)

              {

                   if (intlist[p-1]!=0) i=i+1;

              }

              primelist=new int[i];

              i=0;

              for (int p=2;p<=n;p++)

              {

                   if (intlist[p-1]!=0)

                   {

                       primelist[i]=intlist[p-1];

                       i=i+1;

                   }                 

              }

         }

     }
 

 

这这个算法中,删除的数是那些被从2开始直到n的平方根的整数整除的数。这个算法比起前面介绍的单个素数的寻找方法要好,它的循环次数减少了一多半,但是这个算法还不是最理想的:

 

1.              例如,6既能被2整除,也能被3整除,那么当p=2时,6被删掉了一次;当p=3时,6又被删除了一次,虽然按照我们设定的算法规则,这不会导致冲突(通过判断intlist数组元素是否为0,若为0就不必重复删除),但是这会使得算法的效率低下。

 

2.              还有计算素数序列元素个数时,我们也走了弯路。第一步,我们先计算出了数组元素大小,第二步才开始赋值,事实上这两步我们可以减去计算数组大小这一步,可以把它放在前面完成。

 

3.              已经被删除了的元素,也就是那些不是素数的元素,可以不用拿他们去整除整数,例如4不用拿去整除8,因为能被4整除的数肯定能被2整除,已经在前面循环中被删除了。

 

基于上述考虑,我们得到了一个效率更加高的算法:

 

class primegood

     {

         public static int[] primelist;

         public static void findprime(int n)

         {

              int[] intlist;

              int len=n-1;

              intlist=new int[n];

              for (int p=2;p<=n;p++) intlist[p-1]=p;

              for (int p=2;p<math.sqrt(n);p++)

              {

                   if (intlist[p-1]==0) continue;

                   int j=p*p;

                   while (j<=n)

                   {

                       if (intlist[j-1]!=0 )

                       {

                            intlist[j-1]=0;

                            len=len-1;

                       }

                       j=j+p;

                   }

              }

              primelist=new int[len];

              int i=0;

              for (int p=2;p<=n;p++)

              {

                   if (intlist[p-1]!=0)

                   {

                       primelist[i]=intlist[p-1];

                       i=i+1;

                   }                 

              }

         }

     }
 

 

这个算法思想和前面的算法完全一样,不过改正了上面算法中不完善的一些内容。

 

为了说明这两个算法的效率区别,我们编制了如下的主程序来比较一下他们的差异:

 

static void   main()

         {

              console.writeline("start!");

              datetime mytime5=datetime.now;

              primegood.findprime(100000);

              /*for (int i=0;i<=primegood.primelist.length-1;i++)

              {

                   console.writeline(primegood.primelist[i]);

              }*/

              datetime mytime6=datetime.now;

              timespan timeadd3=mytime6-mytime5;

              console.writeline(timeadd3.ticks);

              datetime mytime1=datetime.now;

              prime.findprime(100000);

              datetime mytime2=datetime.now;

              timespan timeadd=mytime2-mytime1;

              datetime mytime3=datetime.now;

              primegood.findprime(100000);

              datetime mytime4=datetime.now;

              timespan timeadd2=mytime4-mytime3;

              console.writeline(timeadd.ticks);

              console.writeline(timeadd2.ticks);

         }

     }
 

 

通过运行这个程序,可以发现他们的差别是如此的大(前面的算法所耗时间几乎是后面算法的30-60倍),参见下图:


      

    事实上,这两个算法的时间复杂度近似为:⊙(n1.5);⊙(n);可见,对于同一个问题有着多种不同复杂性的算法实现,算法设计是一门十分重要的学问。


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons