筆記一:遞迴,筆記:遞迴
一開始講了演算法的空間複雜度和時間複雜度的分析,其怎麼由來的,一步步的分析演變,以前看過《演算法之道》,這個還有點熟悉,就是具體的例子的時間複雜度的分析不怎麼
會,應多加練習,畢竟
這是很基礎的東西~
然後就是遞迴和分治~ 今晚只夠時間講遞迴~
其實,都看過遞迴~以前剛剛開始接觸的時候覺得很容易,慢慢的就很難了,就是實現代碼的時候碰到了思維障礙,過不去,大二時就學過遞迴~很重要的基礎
以前的印象是調用自身,“推卸責任”,數學公式,遞迴圖,經典的Fibonacci數列~
以前就是看或寫遞迴代碼的時候就會遇到思維障礙,這很難說明,但就是要理解其中的一個環節時卡住了,不明白為什麼~
通過今晚的課,我想,也許是我認識理解遞迴演算法的方式錯誤了~應該充分的把握其本質(要拿出來用時最直接接觸的本質)和“不求甚解”~
今晚,老師將了遞迴的空間本質,其實就是一個棧,臨界結束條件在最頂層,最底層的是n的情況,這個就像是個手榴彈一樣,最頂的就是個保險環,我們要寫的代碼就是保險
環(臨界結束條件)和炸藥(遞迴關係,反應鏈)~這個記憶很重要,因為明確了要寫的是什麼,就不會出現思維障礙了~理解起來就順了,要寫怎麼樣的遞迴代碼就一目瞭然了~
寫遞迴代碼,要先推出臨界結束條件和遞迴關係式,然後再去實現代碼!!!要分析遞迴的時間複雜度也是要先寫出遞迴式分析!!!遞迴:重在“歸”和化歸差不多!
比如,Fibonacci數列f[n]=f[n-1]+f[n-2],分析的話,就是T(n)變為兩個T(n)(T(n-1)和T(n-2)都看為T(n)),就是T(n)=2T(n)+O(1),
每個T(n)都變為2T(n),有n個,即是O(2^n)的複雜度~(其中還有一個O(n),忽略不計)~<注意!這裡的兩個字“變為”是很重要的思想!!!>
還有就是講了全排列~很經典~
perm(n)=(變為)rn(perm(n-1))+rn-1(perm(n-1))......r0(perm(n-1))
遞迴演算法,幾乎都是找f(n)和f(n-1)或f(n/2)等等的關係!
我相信其實這些都很簡單,我知道我所理解的方向不對,即是開啟的方式不對罷了,所以才會學演算法這麼慢!!!加油!!!
問一下:遞迴就是迴圈?
在方法體裡面調用自身的就是遞迴,迴圈裡面沒有
很多初學者往往對遞迴迷惑不解,也在這上面花了不少的時間。其實教材上的例子很經典,只是它說的有一些嘮叨了。初學者會看的頭大的。編程是解決問題的,而現實中很多的問題都是比較簡單的,沒有象漢諾塔那麼複雜。我們也不必追究遞迴到底是怎樣實現的,我們只是要會用遞迴,會用遞迴來為我們解決一些問題,這就行了。
首先來看一個例子:
有一個Febonacci序列:
1,1,2,3,5,8,13,,21,34........
它的問題是:求這個序列中的第N個數。
由於它的函數原形是:f(n)=f(n-1)+f(n-2)
這用遞迴很容易就可以寫出代碼來,一點都不費事:
int Febc(int n) {
if(n<3) return (1);
else
return (Febc(n-1)+Febc(n-2));
}
噢~~~~~也許你會說遞迴真是太簡單了,簡直就是一個數學模型嘛,呵呵。
其實,遞迴函式的工作過程就是自己調用自己。有一些問題用遞迴就很容易解決,簡單的你自己都會吃驚。
我們做事情,一般都是從頭開始的,而遞迴卻是從末尾開始的。比如上面的函數吧,當n>3時,它顯然只能求助於n-1,n-2。而(n-1)>2,(n-2)>2時,它們就求助於:(n-1)-1,(n-1)-2;(n-2)-1,(n-2)-2;然後··············直到(n-k)<3,(n-k-1)<3時,函數Febc終於有了傳回值1 了,它再從頭開始計算,然後一直算到n 為止。
通過上面的例子,我們知道遞迴一定要有一個停止的條件,否則遞迴就不知道停止了。在上面的例子中, if(n<3) return (1); 就是停止的條件。
然而,使用遞迴的代價是十分巨大的:它會消耗大量的記憶體!!遞迴迴圈時它用的是堆棧,而堆棧的資源是十分有限的。上面的例子你只能用一個很小的n值。如果n=20,即Febc(20)的話,它將調用Febc(n)函數10000多次!!!而上面一個例子用迴圈也是十分容易寫的:
/*using turboc2*/
int febc(int);
main()
{
int n;
scanf("%d",&n);
febc(n);
}
int febc(int n)
{
int a[3],i;
a[0]=a[1]=a[2]=1;
for(i=3;i<=n;i++)
a[i%3]=a[(i+1)%3]+a[(i+2)%3]; /*實現 Febc(i)=Febc(i-1)+Febc(i-2)*/
printf("\n%d\n",a[n%3]);
}
有興趣者不妨輸入一個較大的n值,然後比較比較這二個Function Compute的速度。當然, 如果你使用的n太大的話,遞迴可能發生錯誤。如果死機了可別罵我哦~~~ 我已經提醒過你了 :)
現在我們再來看看一個求從1 加到100的迴圈:
/*turboc2*/
main()
{ int i,n;
for(i=1;i<101;i++)
n+=i; }
這很簡單沒什麼可說的。 但是,你能不能寫出相應的遞迴函式呢?...餘下全文>>
一個遞迴演算法的實現問題
shanlang,我現在也在做這。現在做這的人少,做出來的又密閉技術。
我分析了鳶飛的直銷軟體,這種應該用樹形結構來做。
在資料庫做個備忘欄位,按下面的方式儲存。
1
11
12
13
111
112
121
122
131
132
1311
13111
1312
13121
這個東西遞迴查詢資料庫太麻煩。速度還慢
要多在錄入會員時多用冗餘欄位記錄有用資訊。
我的QQ是30635099,有空我們可以深入交流下,我也是用asp實現