一、對算法分析方法的最簡單的理解和使用方法
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;
}
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語言描述的比較直觀。再者算法學習方面比較權威的有一本《算法導論》,這本書講的很有深度,所以認真讀起來還是很有意思的。另外需要糾正一點,語言本身就是來實現算法的載體,所以學透一門語言也是必須的。
不是樓主說的意思吧。
它的意思是你可以初始化一段內存,存放在
Link<Elem>* Link<Elem>::freelist中
當我們需要申請內存的時候,只需要從freelist中快速的取出一段即可
然而,當freelist已經使用完畢後,就調用C++默認的::new來申請
內存;
只不過這段代碼的freelist的初始化部分並沒有給出。