什么是數(shù)據(jù)結(jié)構(gòu)?

    指數(shù)據(jù)元素之間的關(guān)系。這些關(guān)系可以分為:

  集合

  線性結(jié)構(gòu)

  樹形結(jié)構(gòu)

  網(wǎng)狀結(jié)構(gòu)。

 

     邏輯結(jié)構(gòu)分為: 線性結(jié)構(gòu) 和  非線性結(jié)構(gòu)。

 

     集合:除了同屬一個對象外不存在相互關(guān)系。如:汽車上的人除了同輛車彼此間無其他關(guān)系。

       Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 

    線性結(jié)構(gòu):元素間為嚴(yán)格的一對一關(guān)系,即一個元素有且只有一個前驅(qū)。如:成績表中一個學(xué)生一個成績

          Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

    

          樹形結(jié)構(gòu):元素之間為嚴(yán)格的一對多關(guān)系,即一個元素有且只有一個前驅(qū),但可以多個后繼。如家譜,行政組織

     Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 

   網(wǎng)狀結(jié)構(gòu):元素之間存在多對多的關(guān)系,比較復(fù)雜。如:微信朋友圈

     Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 

如何描述數(shù)據(jù)結(jié)構(gòu)?

使用二元組來描述數(shù)據(jù)結(jié)構(gòu)

Data_structure = (D,R)

D 是元素的有限集
R 是D上所有元素的關(guān)系有限集

 

下面舉一些例子

線性結(jié)構(gòu)可以用二元組表示為:

linear = (D,R)
D = {A,B,C,D,E,F,G,H}
R = {r}
r = {<A,B>,<B,C>,<C,D>,<D,E>,<E,F>,<F,G>,<G,H>}

 

樹形結(jié)構(gòu)可以用二元組表示為:

tree = (D,R)
D = {A,B,C,D,E,F,G,H,I,J}
R = {r}
r = {<A,B>,<A,C>,<A,D>,<B,E>,<B,F>,<C,G>,<C,H>,<C,I>,<D,G>}

 

網(wǎng)狀結(jié)構(gòu)可以用二元組表示為:

nets = (D,R)
D = {1,2,3,4,5}
R = {r}
r = {(1,2),(1,3),(1,4),(2,3),(2,4),(2,5),(3,4),(3,5),(4,5)}

 

尖括號表示有向線,圓括號表示無向線。

將上面的尖括號或圓括號的元素用線連一下便是對應(yīng)的形狀了。


數(shù)據(jù)結(jié)構(gòu)如何存儲?
   順序存儲結(jié)構(gòu):數(shù)據(jù)元素依次存儲在一組連續(xù)存儲單元當(dāng)中,數(shù)據(jù)邏輯關(guān)系由存儲單元的位置直接體現(xiàn)。
   鏈?zhǔn)酱鎯Y(jié)構(gòu):數(shù)據(jù)元素存儲在任意存儲單元當(dāng)中,而附加的指針域表示元素之間的邏輯關(guān)系

 

程序 = 算法 + 數(shù)據(jù)結(jié)構(gòu)

數(shù)據(jù)結(jié)構(gòu)離不開算法,下面說說算法 

 

什么是算法?

算法具有五個特性:

  有窮性:一個算法必須在有窮的執(zhí)行步驟后結(jié)束,每步都可以在有窮的時間內(nèi)完成。

  確定性:算法中每條指令必須明確,任何情況下對于相同輸入都有相同的輸出。

  可行性:算法中描述的操作均可以用基本運算的有限執(zhí)行次數(shù)來實現(xiàn)。

  輸入:一個算法有0個或者多個輸入,這些輸入是某個特定對象的合集

  輸出:一個算法至少有一個輸出,與輸入有著某些特定關(guān)系的量。

 

如何設(shè)計算法?

  正確性:除了語法正確,邏輯上也正確,能達(dá)到預(yù)期的目,最好可以驗證結(jié)果是否正確。

  可讀性:方便閱讀,交流,改進(jìn)

  健壯性:輸入非法參數(shù),算法能及時給出錯誤答案,并輸出錯誤提示,同時終止程序。

  效率與存儲:執(zhí)行的時間越短越好,使用的空間越少越好,雖然時間和空間總算矛盾的

 

算法的時間復(fù)雜度

  事后統(tǒng)計:將不同的算法編制成程序,然后比較這些程序執(zhí)行的時間。

  事前估算:用數(shù)學(xué)方法對算法效率直接分析,常用此方法來判斷時間復(fù)雜度。

  事前估算需要考慮的因數(shù):

    1.問題的規(guī)模,排序10個數(shù)字比排序100個數(shù)字時間短

    2.編寫的語言,越高級的語言執(zhí)行的效率越低。

    3.機(jī)器的速度,80386和i7的速度沒得比

    4.算法本身的策略。

  

  由于2,3因數(shù)需要考慮到硬件,軟件(編譯器)等因數(shù),因此用絕對的機(jī)器運行時間來衡量算法

  是不科學(xué)的,所以需要拋開這些因數(shù),主要研究時間效率與算法所處理的問題規(guī)模n的函數(shù)關(guān)系

 

 

當(dāng)隨著問題規(guī)模n增大時,算法執(zhí)行時間的增長率與f(n)的增長率相同,稱為算法的漸進(jìn)時間復(fù)雜度。記作:

T(n) = O(f(n))

執(zhí)行時間 ==  執(zhí)行次數(shù)(假設(shè)執(zhí)行一條語句所用的時間相同),另外下面的時間復(fù)雜度都以最壞的情況考慮

 

下面是常見的時間復(fù)雜度:

常數(shù)階  O(1)

對數(shù)階  O(logn)

線性階  O(n)  

平方階  O(n^2)

立方階  O(n^3)

指數(shù)階  O(2^n)

階數(shù)階  O(n!)

爆炸階  O(n^n)

 

下面兩段代碼是累加求和

1 int sum1(){2   int i,sum=0,n=100;      #執(zhí)行了1次3   for(i=0;i<n;i++)         #執(zhí)行了n+1次4     sum += i;              #執(zhí)行了n次5 }

 

高斯算法

1 int sum2(){2   int n,sum=0;           #執(zhí)行了1次3   sum = n(n+1)/2;        #執(zhí)行了1次4 }

 

上面兩段代碼中 n 是問題的規(guī)模。

第一個算法執(zhí)行次數(shù)為:1 + n+1 + n = 2n+2   

隨著問題規(guī)模n的增加,執(zhí)行次數(shù)以線性增加,所以時間復(fù)雜度為O(n)

第二個算法執(zhí)行次數(shù)為:1 + 1 = 2                   

隨著問題規(guī)模n的增加,執(zhí)行次數(shù)始終為2,所以時間復(fù)雜度為O(1)

 

所以時間復(fù)雜度計算規(guī)則為:

1.如果執(zhí)行的次數(shù)是常數(shù),與規(guī)模n無關(guān),則為O(1)

2.如果執(zhí)行的次數(shù)是多次多項式,取最高項,如:n^3 + n^2 則為O(n^3)

3.如果執(zhí)行的次數(shù)是含有系數(shù)和常數(shù),可以忽略系數(shù)和常數(shù),如: 2n^2 + 3 則為O(n^2)

 

有了上面的法則,來分析下下面這些算法的時間復(fù)雜度,n均代表問題規(guī)模。

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 1 #define n 10 2 int multiMatrix(int a[n][n],b[n][n],c[n][n]){ 3   for(i=0;i<=n;i++)                    #執(zhí)行了n+1次 4      for(j=0;j<n;j++){                  #執(zhí)行了(n+1)*n次 5         c[i][j] = 0;                      #執(zhí)行了n^2 6         for(k=0;k<n;k++)                  #執(zhí)行了n^2*(n+1)次 7            c[i][j] = c[i][j] +a[i][k] * b[k][i];   #執(zhí)行了n^3 8  9      }10 }

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 T(n) = 2n^3 + 3n^2 + 2n + 1  所以時間復(fù)雜度為O(n^3)

 

1 int fun(){2    i=1;n=100;3    while(i<n){4          i = i * 2;5    }6 }

 假設(shè)上面的算法執(zhí)行了x次后停止。則有 2^x >= n,所以 x = log(2)n,所以時間復(fù)雜度為O(logn)

 

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 1 void prime(n){ 2     i=2; 3     while( (n%i)!=0  && i*1.0<sqrt(n) )  #如果不能被整除,且小于根號n,則繼續(xù)執(zhí)行 4        i++; 5  6     if(i*1.0>sqrt(n)) 7        printf("%d是個素數(shù)\n",n); 8     else 9        printf("%d不是素數(shù)\n",n);10 11 }

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

函數(shù)作用判斷n是否為素數(shù),原理就是遍歷開區(qū)間(1,n)間的數(shù),然后看看遍歷的數(shù)能否被整除。

事實上如果 n^1/2 (根號n)前不存在一個數(shù)能被n整除,那么n^1/2(根號n)之后的數(shù)也不會被n整除

這是因為對稱性。因此只需要判斷 n^1/2(根號n)之前的數(shù)字是否存在一個能被n整除的數(shù)即可。

所以隨著問題規(guī)模n的增加,執(zhí)行的次數(shù)增長率與 f(n)=n^1/2 的漸進(jìn)增長率相同,所以T(n)=O(n^1/2)

 

后面還有幾道具有挑戰(zhàn)的題目,這里先講講空間復(fù)雜度:

 

算法的空間復(fù)雜度

指算法對運算所需要的輔助工作單元和存儲為實現(xiàn)計算所需信息輔助性的空間大小,記作:

S(n) = O(f(n));

 這個大小不包括輸入數(shù)據(jù)占用的空間,大小是由具體的實際問題來決定的。

 

下面一個例子:判斷三個數(shù)字中,哪個數(shù)最大

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 1 max(int a,b,c){ 2   if(a>b){ 3       if(a>c)return a; 4       else return c; 5   } 6   else{ 7       if(b>c)return b; 8       else return c; 9   }10 }

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 隨著問題規(guī)模增大,執(zhí)行的次數(shù)也增大,時間復(fù)雜度為O(n)

 

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

1 max(int a[3]){2   c=a[0];3   for(i=0;i<3;i++)4      if(a[i]>c)c=a[i];5 6   return c;7 }

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 隨著問題規(guī)模增大,執(zhí)行的次數(shù)也增大,時間復(fù)雜度也為O(n)

 

上面兩個例子時間復(fù)雜度相同都為O(n),但第一個算法無需額外的空間,而第二個算法需要兩個變量輔助。

所以第一個算法空間復(fù)雜度優(yōu)于第二個算法,但是當(dāng)問題規(guī)模不是3 而是100的時候,相信沒人會用第一個

算法,因為會寫到手殘。

 

歡迎各位轉(zhuǎn)載,請指明出處:http://www.cnblogs.com/demonxian3/p/7075441.html

 

最后來幾個練習(xí)題,評論附上答案

選擇題

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

1 int fun(int n){2   i=1,s=1;3   while(s<n)4     s += ++i;5 6   return i;7 }

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 A. O(n/2)    B. O(logn)   C. O(n)    D.O(n^1/2)

 

for(int i=0;i<m;i++)     for(int j=0;j<n;i++)
         a[i][j] = i*j;

 A. O(m^3)    B. O(n^2)   C. O(m*n)    D.O(m+n)

 

計算題,設(shè)n為整數(shù)求下面的時間復(fù)雜度

(1)

1 i=1,j=0;2 while(i+j<n)3   if(i>j) j=j+1;4   else    i=i+1;

 (2)

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

1 x=91,y=100;2 while(y>0)3   if(x>100){4      x=x-10;5      y=y-1;6   }7   else8     x=x+1;

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 (3)

1 x=n2 while(x>=(y+1)*(y+1))3   y=y+1;

 

程序員最高境界:靜若癱瘓,動若癲癇

http://www.cnblogs.com/demonxian3/p/7075441.html