bash(awk遞歸)N階【斐波那契數列】多種實現(含遞歸解析圖)

【版權所有】轉載請說明作者【Jev Tes】
       【本文導航】
       零、關于斐波那契數列
       一、輸入參數合法性判斷
       二、TYP 1:常規累加法
       三、TYP 2:數組傳遞法
       四、TYP 3:遞歸法
           1、shell遞歸
           2、awk優化遞歸
       五、效率比較

   


零、關于斐波那契數列
    斐波那契數列又稱黃金分割數列,因數學家列昂納多·斐波那契以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列: 0、 1、 1、 2、 3、 5、 8、 13、 21、 34、 ……,這個數列從第3項開始,每一項都等于前兩項之和。
    斐波納契數列以如下被以遞歸的方法定義: F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2)( n≥2)


一、輸入參數合法性判斷

    編寫腳本/函數時,對輸入參數合法性的判斷非常重要,可以規避很多不必要的麻煩,特別是調試遞歸函數時!

#--------------------------------輸入參數合法性判斷--------------------------------
if ! echo $1 | egrep "^[0-9]+$"  &> /dev/null ; #如果輸入不是0或正整數,執行下面語句
then
    echo "-Fib 119:error token is \""$1"\"!"   #回顯錯誤信息
    exit 110                     #退出腳本
fi
#------------------------------------------------------------------------------

二、TYP 1:常規累加法
    整體思路:從第3階開始計算F3=F2+F1=1+1=2、F4=F3+F2=2+1=3…依次計算到第N階;
    主體代碼跟分析如下:

#--------------------------------累加算法--------------------------------
fib()                             #定義函數
 { 
local i=2                         #本地變量,做計數用
local Fib0=0                      #本地變量,記錄傳遞F(n-2)的值,初始值為F0的值
local Fib1=1                      #本地變量,記錄傳遞F(n-1)的值,初始值為F1的值
local $Fibn                       #本地變量,記錄傳遞F(n)的值
[ $1 -eq 0  ] && echo "F(0)=0" && return 0  #如果$1值為0,直接回顯F(0)=0,退出函數
[ $1 -eq 1  ] && echo "F(1)=1" && return 1  #如果$1值為1,直接回顯F(1)=1,退出函數
until  [ $i -gt $1  ] ; do        #當$i大于$1(計算階數)時,退出循環
Fibn=$[Fib1+Fib0]                 #Fn=F(n-1) +F(n-2),n為此時$i的值
Fib0=$Fib1                        #將當前F(n-1)的值,即為下輪F(n-2)的值
Fib1=$Fibn                        #將當前F(n)的值,即為下輪F(n-1)的值
i=$[i+1]                          #對$i進行累加1
done 
echo  "F("$1")=$Fibn"             #退出循環后,輸出Fn的值
 }
fib $1                            #引用函數

三、TYP 2:數組傳遞法
    整體思路:跟常規累加傳遞法類似,從第3階開始計算,依次計算到第N階,但這方法奇妙在于用數組來儲存整個數列,可以將整個數列完整保存下來;
    主體代碼跟分析如下:

#--------------------------------數組傳遞法--------------------------------
fib()                        #定義函數
{
declare -a Fib               #定義數組Fib
Fib[0]=0                     #賦值F0=0
Fib[1]=1                     #賦值F1=1
Fib[2]=1                     #賦值F1=1
case $1 in
0)
    echo ${Fib[0]}           #如果$1值為0,直接回顯F(0)=0
    ;; 
1)
    echo ${Fib[1]}           #如果$1值為0,直接回顯F(0)=0
    ;;
*)
    for i in `seq 2 $1`;do   #$i在2-$1時進行循環
    Fib[$i]=$[${Fib[$i-1]}+${Fib[$i-2]}]  #Fib[$i]的值為前兩項的值之和
    done
    echo ${Fib[$1]}          #退出循環后,輸出Fn的值
    ;;
esac
}
fib $1                       #引用函數


四、TYP 3:遞歸法
   整體思路:跟以上倆種思路相反,函數從N階開始,依次向下遞歸展開,直到$1=1,$1=0,時停止遞歸,并將值回傳給父函數;
   主體代碼跟分析如下:
       1、shell遞歸 

#-------------------------------shell遞歸---------------------------------
Fib()                         #定義函數 
{ if [ $1 -eq 0 ]  ;
then   echo 0                   #當$1值為0,回顯0
elif [ $1 -eq 1 ]  ;then   echo 1     #當$1值為0,回顯1
else   echo $[$(Fib $[$1-1])+$(Fib $[$1-2])]    
 #遞歸展開Fn=F(n-1)+F(n-2)直到$[$1-1]=1,$[$1-2]=0,遞歸終止fi} 
Fib $1                       #引用函數

       2、awk優化遞歸 

#--------------------------------awk遞歸算法--------------------------------
awk -v i=$1  'function Fib(i){
if(i==0){ return 0}               #當$i值為0,返回0
else if(i==1){return 1}           #當$i值為0,返回0
else{return Fib(i-1)+Fib(i-2)}    #展開遞歸,計算Fib(i-1)+Fib(i-2)的值
}BEGIN{ print Fib(i)}'

簡單遞歸思路解析:(以4階為例,即$1=4)
F4=F3+F2 

    =(F2+F1)+(F1+F0)      
    =[(F1+F0)+F1]+(F1+F0) 
    =3F1+2F0 
    =3
   遞歸解析圖如下:(以4階為例,即$1=4)
   遞歸-兔子數列.png

五、效率比較
   測試環境
   虛擬平臺:VMware
   虛擬機系統:centos6.8
   虛擬機配置:CPU*2(宿主主機CPUI56300),內存1664MB
簡單測試結果如下
     常規累加法
   遞歸-兔子數列1.png
     數組傳遞法
   遞歸-兔子數列2.png
     shell遞歸
   遞歸-兔子數列3.png
     awk優化遞歸
   遞歸-兔子數列4.png
   從這個簡單的測試可以得出:
    從算法角度來說,直接累加運算效率最高,數組傳遞算法略遜些,由于遞歸比較耗資源,效益最低;
    從計算速度來講awk計算高于bash計算;
注:遞歸計算時間資源消耗都隨著階數的變化呈指數性增長
    

     

【點擊返回頁首】

【版權所有】轉載請說明作者【Jev Tes】

原創文章,作者:Jev Tse,如若轉載,請注明出處:http://www.www58058.com/60651

(0)
Jev TseJev Tse
上一篇 2016-11-24
下一篇 2016-11-24

相關推薦

  • shell腳本4——特殊循環和函數

    循環的特殊用法: 1、while循環的特殊用法之遍歷文件的每一行 while read line; do     循環體 done < /PATH/FROM/SOMEFILE 依次讀取/PATH/FROM/SOMEFILE文件中的每一行,將每一行賦值給變量line…

    Linux干貨 2016-08-21
  • 初學Linux之文件查找和壓縮

    使用locate命令 ,使用find命令 ,壓縮和解壓縮工具

    2018-01-13
  • 什么是文件系統

    文件系統:層級結構;有索引; /: 原初起點; 倒置樹狀結構; /dev/pts/2: 最左側/: 表示根目錄 其它的/: 表示路徑分隔符 Linux的路徑分隔符是/ Windows的是\ 文件的路徑表示: 絕對路徑:從根開始表示出的路徑  相對路徑:從當前位置開始表示出的路徑 文件名使用法則: 嚴格區分字符大小寫:file1, File1, FI…

    Linux干貨 2016-10-29
  • Linux文件查找及壓縮

    Linux文件查找(locate & find) locate     查詢系統上預建的文件索引數據庫(速度快,但更新不實時)     /var/lib/mlocate/mlocate.db     依賴于事先構建的索引 &nbsp…

    Linux干貨 2016-08-19
  • lvs-DR模型構建高性能集群

    構建環境:centos7.1     Diretor server:172.16.15.131  (  VIP:172.16.15.138 )     Real server:172.16.15.132/133      配置163源 拓撲…

    Linux干貨 2016-08-22
  • SSH會話劫持實現端口轉發

    在進行滲透測試時,我們有時候會碰到搭建的測試環境、產品服務器、DMZ或者其他類似的機器群的情況,這時我們完全可以把它們看作跳板。這些系統被設計成對外交互的接口,這時候我們考慮對其他域里的用戶進行SSH會話劫持是個不錯的選擇。 那么如果你擁有了某一個跳板的控制權限,想要通過另一個域的用戶對遠程域進行訪問會怎么辦呢?當然,這時候你是沒有密碼、密鑰的,你不能拋棄二…

    系統運維 2015-03-23
欧美性久久久久