明輝手游網(wǎng)中心:是一個免費提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

C#算法設(shè)計與區(qū)分-尋找素數(shù)

[摘要]在這篇文章中,我將使用C#編制兩個尋找素數(shù)的算法,說明算法設(shè)計的重要性以及算法的分析。 素數(shù)尋找問題由來已久,一直是一些數(shù)學(xué)家追求的目的。關(guān)于素數(shù)的定義及性質(zhì),我就不在這里多敘了,相信大家都對此了如指掌。素數(shù)的尋找思路比較的簡單,根據(jù)素數(shù)的性質(zhì)(素數(shù)應(yīng)該不能被除了1和它自身的其他數(shù)整除...

    在這篇文章中,我將使用C#編制兩個尋找素數(shù)的算法,說明算法設(shè)計的重要性以及算法的分析。

       素數(shù)尋找問題由來已久,一直是一些數(shù)學(xué)家追求的目的。關(guān)于素數(shù)的定義及性質(zhì),我就不在這里多敘了,相信大家都對此了如指掌。素數(shù)的尋找思路比較的簡單,根據(jù)素數(shù)的性質(zhì)(素數(shù)應(yīng)該不能被除了1和它自身的其他數(shù)整除)我們可以從最小的素數(shù)2開始,一直到比它小1的數(shù)為止,用這些數(shù)去整除它,如果它能被整除則它必定不是素數(shù),這是判斷單個素數(shù)的方法(這個算法思想最簡單,時間復(fù)雜度最大)。對于尋找比某一個給定的整數(shù)值小的所有素數(shù)也可以采用這種方法,不過我們會發(fā)現(xiàn),采用這種單個判斷的方法所耗的時間比較多。比如查找不大于10的素數(shù),我們必須從2開始一個個判斷,共需判斷9個數(shù),事實上按照我們后面講述的方法,只需循環(huán)2次就可以了。因此,下面的兩種方法都將基于刪除法來做。

       我們來看看刪除法的思想:

1.  將小于給定整數(shù)值n的所有正整數(shù)加到一個數(shù)組中;

2.  刪除能夠被一些整數(shù)整除的數(shù);

3.  數(shù)組中遺留的元素就是最后要得到的素數(shù)序列。

對于第二步,我們將給出兩種方法來實現(xiàn)。我們先來看看算法:

算法一:

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]% 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;

                   }                 

              }

         }

     }
 

 

這這個算法中,刪除的數(shù)是那些被從2開始直到n的平方根的整數(shù)整除的數(shù)。這個算法比起前面介紹的單個素數(shù)的尋找方法要好,它的循環(huán)次數(shù)減少了一多半,但是這個算法還不是最理想的:

 

1.              例如,6既能被2整除,也能被3整除,那么當(dāng)p=2時,6被刪掉了一次;當(dāng)p=3時,6又被刪除了一次,雖然按照我們設(shè)定的算法規(guī)則,這不會導(dǎo)致沖突(通過判斷IntList數(shù)組元素是否為0,若為0就不必重復(fù)刪除),但是這會使得算法的效率低下。

 

2.              還有計算素數(shù)序列元素個數(shù)時,我們也走了彎路。第一步,我們先計算出了數(shù)組元素大小,第二步才開始賦值,事實上這兩步我們可以減去計算數(shù)組大小這一步,可以把它放在前面完成。

 

3.              已經(jīng)被刪除了的元素,也就是那些不是素數(shù)的元素,可以不用拿他們?nèi)フ麛?shù),例如4不用拿去整除8,因為能被4整除的數(shù)肯定能被2整除,已經(jīng)在前面循環(huán)中被刪除了。

 

基于上述考慮,我們得到了一個效率更加高的算法:

 

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;

                   }                 

              }

         }

     }
 

 

這個算法思想和前面的算法完全一樣,不過改正了上面算法中不完善的一些內(nèi)容。

 

為了說明這兩個算法的效率區(qū)別,我們編制了如下的主程序來比較一下他們的差異:

 

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);

         }

     }
 

 

通過運行這個程序,可以發(fā)現(xiàn)他們的差別是如此的大(前面的算法所耗時間幾乎是后面算法的30-60倍),參見下圖:


      

    事實上,這兩個算法的時間復(fù)雜度近似為:⊙(n1.5);⊙(n);可見,對于同一個問題有著多種不同復(fù)雜性的算法實現(xiàn),算法設(shè)計是一門十分重要的學(xué)問。