程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 《數據結構與算法分析》學習筆記(二)——算法分析,數據結構與算法分析

《數據結構與算法分析》學習筆記(二)——算法分析,數據結構與算法分析

編輯:C++入門知識

《數據結構與算法分析》學習筆記(二)——算法分析,數據結構與算法分析


一、對算法分析方法的最簡單的理解和使用方法

1、首先大家可能一般會被那些數學的概念搞暈,其實簡單理解下來,就是假設任何語句執行的效率都是一樣的,所以設定每一個語句的執行時間都是一個時間單位,那麼只要計算這個程序到底執行了多少語句,就可以算出其時間復雜度。

2、其次就是我們要明白,我們是個估算,所以可以進行化簡,明顯我們可以忽略那些相對來說低階的項,只分洗最高階項。然後主要就是有這些常見的法則:

(1)FOR循環

一次for循環的運行時間至多是該for循環內語句的運行時間乘以迭代次數。

(2)嵌套的FOR循環

肯定是計算最內層循環語句的執行次數,然後再乘以所以循環的迭代次數。

(3)整個程序

其實找到循環迭代次數最多,嵌套最多的進行計算就好。

3、當然,我們計算的只是大概值,而且為了計算的簡便,我們一邊進行適當的放大,即只考慮最壞最壞的情況,算出其時間復雜度即可。

二、最大子序列

書中通過4種不同的解法來進一步強化我們應該如何計算時間復雜度,小白我也好好學習了下,在此寫下學習筆記。

題目:算出一個整數序列中最大的子序列的值。

算法一:

int MaxSubsequenceSum1(const int A[],int N)

{

int thisSum , MaxSum;

MaxSum=0;

for (int i =0; i<N; i++)

{

for (int j=i; j<N; j++)

{

thisSum=0;

for (int K =i; K<=j; K++)

{

thisSum+=A[K];

}

if(thisSum>MaxSum)

{

MaxSum=thisSum;

}

}

}

  

if(MaxSum==0)

{

int i;

for(i=0;i<N;i++)

{

if(A[i]!=0)

break;

}

if(i!=N)

{

int Max=A[0];

for(int j=0;j<N;j++)

{

if(A[j]>Max)

{

Max=A[j];

}

}

MaxSum=Max;

  

}

}


  

  

return MaxSum;

  

}


我們可以看出其最大的for循環有三重,而且最壞的可能迭代次數都是N,所以我們可以很容易的得出,此算法的時間復雜度為O(N^3),其中資源最明顯的浪費就在重復計算了從低i到第k的子序列的值,所以算法二便是進行了簡單的修改。
算法二:

int MaxSubsequenceSum2(const int A[],int N)

{

int thisSum,MaxSum;

MaxSum=0;

for (int i=0; i<N; i++)

{

thisSum=0;

for (int j=i; j<N; j++)

{

thisSum+=A[j];

if(thisSum>MaxSum)

{

MaxSum=thisSum;

}

}

}

  

  

if(MaxSum==0)

{

int i;

for(i=0;i<N;i++)

{

if(A[i]!=0)

break;

}

if(i!=N)

{

int Max=A[0];

for(int j=0;j<N;j++)

{

if(A[j]>Max)

{

Max=A[j];

}

}

MaxSum=Max;

  

}

}

  

  

return MaxSum;


}


其實改變的地方即使采用的累加的策略而已,但卻使效率大大的提高了,所以這裡也是提高算法效率的一個小小的技巧,即盡力減少不必要的計算,盡量利用現有的計算結果。
算法三:

int Max3(const int a,const int b,const int c)

{

int temp = (a>b)?a:b;

temp=(temp>c)?temp:c;

return temp;

}




int MaxSubSum(const int A[],int Left,int Right)

{

int MaxLeftSum,MaxRightSum;

int MaxLeftBorderSum,MaxRightBorderSum;

int LeftBorderSum,RightBorderSum;

  

if(Left==Right)

{

if(A[Left]>0)

return A[Left];

else

return 0;

}

  

int center=(Right+Left)/2;

  

MaxLeftSum=MaxSubSum(A, Left, center);

MaxRightSum=MaxSubSum(A, center+1, Right);

  

LeftBorderSum=MaxLeftBorderSum=0;

for(int i=center;i>=Left;i--)

{

LeftBorderSum+=A[i];

if(LeftBorderSum>MaxLeftBorderSum)

{

MaxLeftBorderSum=LeftBorderSum;

}

}

  

RightBorderSum=MaxRightBorderSum=0;

for(int i=center+1;i<=Right;i++)

{

RightBorderSum+=A[i];

if (RightBorderSum>MaxRightBorderSum)

{

MaxRightBorderSum=RightBorderSum;

}

}

  

return Max3(MaxLeftSum,MaxRightSum,MaxLeftBorderSum+MaxRightBorderSum);

  

}


int MaxSubsequenceSum3(const int A[],int N)

{

int MaxSum = MaxSubSum(A, 0, N-1);

  

if(MaxSum==0)

{

int i;

for(i=0;i<N;i++)

{

if(A[i]!=0)

break;

}

if(i!=N)

{

int Max=A[0];

for(int j=0;j<N;j++)

{

if(A[j]>Max)

{

Max=A[j];

}

}

MaxSum=Max;

  

}

}


return MaxSum;

}


這個算法使用了分治的思想,還有遞歸的思想,即把一個問題不斷的分解成類似的規模更小的子問題來解決,所以這裡我們要求一個序列的最大子序列,其實就是求左半部分,有伴部分和中間部分的最大子序列,而求左半部分,後半部分的最大子序列顯然是將問題的規模變小了,所以可以遞歸使用,直到剩下一個數的情況.而中間部分呢,則取左右兩邊,左邊從右往左,右邊從左往右的最大子序列。然後加起來作為中間部分的值,最後比較中間部分,左半部分,後半部分三部分的值就可以得到結果啦。



算法四:

int MaxSubsequenceSum4(const int A[],int N)

{

int thisSum,MaxSum;

thisSum = MaxSum=0;

  

for(int i=0;i<N;i++)

{

thisSum+=A[i];

if(thisSum>MaxSum)

{

MaxSum=thisSum;

}

else if(thisSum<0)

{

thisSum=0;

}

}

  

  

if(MaxSum==0)

{

int i;

for(i=0;i<N;i++)

{

if(A[i]!=0)

break;

}

if(i!=N)

{

int Max=A[0];

for(int j=0;j<N;j++)

{

if(A[j]>Max)

{

Max=A[j];

}

}

MaxSum=Max;

  

}

}

  

return MaxSum;

}



最後一個算法就比較牛逼啦,這個算法竟然只是N階的,大家可以想想這個算法的速度有多快,而且如果不考慮全是負數的情況的話,還可以做到隨時讀入,隨時釋放內存的強大功能,在此深深膜拜一下。









學習《數據結構與算法分析》用哪種語言描述比較好?C/C++?

如果你對C++不是非常熟悉的話,學習算法的時候還是看C語言描述的比較直觀。再者算法學習方面比較權威的有一本《算法導論》,這本書講的很有深度,所以認真讀起來還是很有意思的。另外需要糾正一點,語言本身就是來實現算法的載體,所以學透一門語言也是必須的。
 

《數據結構與算法分析》(C++版第二版)中的“可利用空間表”的實現代碼的疑問

不是樓主說的意思吧。
它的意思是你可以初始化一段內存,存放在
Link<Elem>* Link<Elem>::freelist中
當我們需要申請內存的時候,只需要從freelist中快速的取出一段即可
然而,當freelist已經使用完畢後,就調用C++默認的::new來申請
內存;
只不過這段代碼的freelist的初始化部分並沒有給出。
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved