1. 程式人生 > 其它 >資料結構與演算法(1)資料組織方式、空間利用率、演算法的重要性——ZJU

資料結構與演算法(1)資料組織方式、空間利用率、演算法的重要性——ZJU

資料結構與演算法(1)資料組織方式、空間利用率、演算法的重要性——ZJU

1.1資料結構基本概念

1.1.1解決問題方法的效率, 跟資料的組織方式有關

思考問題:如何在書架上擺放圖書?

不同的擺放方法(即資料的組織方式),影響著插入新圖書與查詢圖書的效率(即解決問題方法的效率),例如,亂放與按類歸類後按字母順序排列。

故有:解決問題方法的效率, 跟資料的組織方式有關


1.1.2解決問題方法的效率, 跟空間的利用效率有關

迴圈法與遞迴法實現例子

例2:寫程式實現一個函式PrintN,使得
傳入一個正整數為N的引數後,能順序
列印從1到N的全部正整數

迴圈法:

void PrintN ( int N )
{ int i;
for ( i=1; i<=N; i++ ){
printf(“%d\n”, i );
}
return;
}

遞迴法:

void PrintN ( int N )
{ if ( N ){//N!=0時進行遞迴呼叫,N==0時直接返回,故列印時從1開始
PrintN( N – 1 ); 
printf(“%d\n”, N );
}
return;
} 

執行後會發現遞迴法並不能滿足要求,直接跳出(吃記憶體),迴圈法正常執行。

故有:解決問題方法的效率, 跟空間的利用效率有關


1.1.3解決問題方法的效率, 跟演算法的巧妙程度有關

冪指數多項式求和——迴圈累次相加和秦九韶演算法

寫程式計算給定多項式在給定點x
處的值

//迴圈累次相加:

double f( int n, double a[], double x )
{ int i;
double p = a[0];
for ( i=1; i<=n; i++ )
p += (a[i] * pow(x, i)); 
return p;
} 

//秦九韶演算法:

double f( int n, double a[], double x )
{ int i;
double p = a[n];
for ( i=n; i>0; i-- )
p = a[i-1] + x*p;
return p;
} 

兩者的執行時間是不相同的,進行執行測試:

其中注意幾點:

  1. 使用clock()進行時鐘計時

    clock():捕捉從程式開始執行到clock()被呼叫時所耗費的時間。這個
    時間單位是clock tick,即“時鐘打點”。
    //其中常數CLK_TCK(或CLOCKS_PER_SEC):機器時鐘每秒所走的時鐘打點數
    
  2. 當執行程式的時間太短但必須要進行計時時,可以重複執行N次(迴圈),測算時間後/N。

普通的執行一次計時程式:

#include <stdio.h>
#include <time.h>
clock_t start, stop;/* clock_t是clock()函式返回的變數型別 */
double duration;/* 記錄被測函式執行時間,以秒為單位 */
int main ()
{ /* 不在測試範圍內的準備工作寫在clock()呼叫之前*/
start = clock(); /* 開始計時 */
MyFunction(); /* 把被測函式加在這裡 */
stop = clock(); /* 停止計時 */
duration = ((double)(stop - start))/CLK_TCK;
    /* 計算執行時間 */
    /* 其他不在測試範圍的處理寫在後面,例如輸出duration的值 */
return 0;
} 

添加了重複執行後的實現程式:

#include <stdio.h>
#include <time.h>
#include <math.h>
define MAXK 1e7 /* 被測函式最大重複呼叫次數 */
clock_t start, stop; 
double duration;
#define MAXN 10 /* 多項式最大項數,即多項式階數+1 */
double f1( int n, double a[], double x );
double f2( int n, double a[], double x );
int main ()
{ int i;
double a[MAXN]; /* 儲存多項式的係數 */
for ( i=0; i<MAXN; i++ ) a[i] = (double)i; 
start = clock();
for ( i=0; i<MAXK; i++ ) /* 重複呼叫函式以獲得充分多的時鐘打點數*/
	f1(MAXN-1, a, 1.1);
stop = clock();
duration = ((double)(stop - start))/CLK_TCK/MAXK; 
printf("ticks1 = %f\n", (double)(stop - start));
printf("duration1 = %6.2e\n", duration);
start = clock();
for ( i=0; i<MAXK; i++ ) /* 重複呼叫函式以獲得充分多的時鐘打點數*/
	f2(MAXN-1, a, 1.1); 
stop = clock();
duration = ((double)(stop - start))/CLK_TCK/MAXK; 
printf("ticks2 = %f\n", (double)(stop - start));
printf("duration2 = %6.2e\n", duration);
return 0
}

故有:解決問題方法的效率, 跟演算法的巧妙程度有關


1.1.4抽象資料型別(Abstract Data Type )

  • 資料型別

    ​ 資料物件集

    ​ 資料集合相關聯的操作集

    (可能面向物件的程式語言更容易理解。)

  • 抽象:描述資料型別的方法不依賴於具體實現

​ 與存放資料的機器無關

​ 與資料儲存的物理結構無關

​ 與實現操作的演算法和程式語言均無關

只描述資料物件集和相關操作集 “是什麼 ”,並不涉及 “如何做到 ”的問題


個人的理解:

  • 抽象資料型別類似於“概念”一說,並不涉及具體、個別,而是使用抽象的概括進行說明,可以認為即為大綱,不過分細分內容,不涉及如何具體實現,該抽象資料型別可以適用於個別具體的物件(物件集和操作集)。
  • 資料結構的含義,大體為資料物件中資料的聯絡及對資料的操作、函式。
  • 該節課講的內容為:資料組織方式、空間利用率、演算法的重要性。