1. 程式人生 > >C產生正態分佈隨機數寫入檔案並讀出後用快速排序法排序

C產生正態分佈隨機數寫入檔案並讀出後用快速排序法排序

基於快速排序法的正態隨機數排序

  • 使用中心極限定理產生正態分佈隨機數
  • 使用快速排序法進行排序
  • 讀寫資料到記事本
  • 程式計時
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define N 1000000

double norm(double mu,double sigma)
{
    double x,stdnorm,sum=0.0;int j;

    for(j=1;j<=12;j++)
    {sum=sum+rand()/(RAND_MAX+1.0
);} stdnorm=sum-6; x=sigma*stdnorm+mu; return x; } void QKSORT(int min_index,int max_index) { extern double data[N]; if(max_index<=min_index+1&&data[min_index]<=data[max_index]) return; double model=data[min_index],temp; int begin_index=min_index,terminal_index=max_index; if
(max_index<=min_index+1&&data[min_index]<=data[max_index]) return; max_index++; while(min_index!=max_index) { for(max_index=max_index-1;max_index>=min_index;max_index--) { if(data[max_index]<model||max_index==min_index) break
; } if(max_index==min_index) break; for(min_index=min_index+1;min_index<=max_index;min_index++) { if(data[min_index]>model||min_index==max_index) break; } if(max_index!=min_index) {temp=data[min_index]; data[min_index]=data[max_index]; data[max_index]=temp;} } data[begin_index]=data[max_index];data[max_index]=model; if(begin_index<max_index-1) QKSORT(begin_index,max_index-1); if(max_index+1<terminal_index) QKSORT(max_index+1,terminal_index); } double data[N]; void main() { int i;clock_t sort_start,sort_end,rand_start,rand_end; void QKSORT(int min_index,int max_index); double norm(double mu,double sigma); double data0; rand_start=clock(); srand(time(0)); FILE *fp; fp=fopen("D:\\data.txt","w+"); for(i=0;i<=N-1;i++) {data0=norm(0,1); fprintf(fp,"%lf\n",data0); } fclose(fp); rand_end=clock(); sort_start=clock(); if((fp=fopen("D:\\data.txt","r"))==NULL) { printf("cannot find what you need,please check it!"); exit(0); } for(i=0;i<=N-1;i++) {fscanf(fp,"%lf",&data[i]); //printf("%lf\t",data[i]); } fclose(fp); QKSORT(0,N-1); sort_end=clock(); fp=fopen("D:\\data_sorted.txt","w+"); for(i=0;i<=N-1;i++) fprintf(fp,"%lf\n",data[i]); fclose(fp); //for(i=0;i<=N-1;i++) // printf("%lf\n",data[i]); /*不建議打印出來,列印時間較慢,排序前後文件已儲存到D盤,請檢視*/ printf("產生%d個隨機數並儲存所用的時間為%lf秒\n讀取資料並用快速排序法排序所用時間為%lf秒\n\n\n",N,(double)(rand_end-rand_start)/CLOCKS_PER_SEC,(double)(sort_end-sort_start)/CLOCKS_PER_SEC); }

執行結果

程式說明

  1. 定義函式norm用於隨機產生一個服從均值為mu,標準差為sigma的正態分佈隨機數。其中stdnorm為由利用中心極限定理產生的服從標準正態分佈的數值,為何使用for迴圈迴圈12次等相關細節處理,請自行百度”中心極限定理“。(以下及以後文中提到的細節方面的處理,請自行查詢,不再贅述,在此做統一說明。)主函式中的srand和rand配合使用,避免c偽隨機數每次產生的隨機數數值都一樣。
  2. 定義第二個函式QKSORT,意指quike sort,表示快速排序法。輸入為數值的最小和最大下標,對陣列進行從小到大的排序。快速排序法是基於氣泡排序法的一個改進,雖然不是最快的演算法,本人認為確實性價比最高的排序方法,值得一學。
  3. 快速排序法的主要思想:在一列數中隨意取一個數作為標兵,不妨就取第一個數,在剩下的數中,先從右邊(數列後定義為右)起,從右到左找到第一個比標兵小的數,記下來。接著從左起,從左到右找到第一個比標兵大的數,也記下來。把找到的兩個數交換位置。接著從之前右邊找到那個比標兵小的數原來的位置起,從右到左再次開始搜尋比標兵小的數,左邊如是,再交換……直到從右邊開始搜尋和從左邊開始搜尋碰頭了,這時再碰頭的位置,左邊的數都比標兵小,右邊的數都比標兵大,想辦法把標兵插到當中去,使得標兵左邊的數都比標兵小,右邊的數都比標兵大,就算完成了一次排序。接著以標兵為分界點,將一次排序後的數列分成兩個部分,對兩個部分同樣所述方法進行排序,一直進行下去,若干次以後,整個數列就按從小到大的順序排好了。想法比較簡單,但中間有一些細節不好處理,請自行想辦法。實在想不出來,請參考我的程式。
  4. 快速排序法,用了遞迴的思想。我寫得比較籠統,欲進一步瞭解,請點選這裡
  5. 讀寫檔案的格式為:
FILE *fp;
fp=fopen("D:\\data.txt","w+");
fclose(fp);


------------------------------------------------------

FILE *fp;
    if((fp=fopen("D:\\data.txt","r"))==NULL)
    {
        printf("cannot find what you need,please check it!");
        exit(0);
    }

fprintf(fp,"%lf\n",data);
fclose(fp);
  1. 計時要用到標頭檔案time.h,計時的函式有很多,有clock(),time()等。請自行腦補。

幾點需要注意的地方

  • 注意要用到的標頭檔案,寧可多,不可少。
  • 主函式內的動態陣列元素個數不能超過130000,申請不到空間,容易出錯,注意將陣列改寫成static或者全域性變數。
  • 使用printf函式列印將花費不少時間,資料量較大時,建議直接儲存到txt檔案中。
  • 看別人程式是一件蠻痛苦的事情,建議掌握好演算法思想後,自己動手寫程式,網上有大量資源可供參考。
  • vc++6.0除了報錯摁F4之外,還要學會除錯。

初次寫CSDN部落格文章,有許多不周到的地方,歡迎指教。有任何問題也可加我QQ962907540一起討論。