大話理論-瞭解算法01

嵌入式開發,難免會碰到一些用C去實現一些算法,或者基於某個算法調整一些參數的工作內容。最近看了一本《算法圖解》,一個講算法入門的書,我本着將書讀薄的理念,將此書的脈絡摘出來,針對不同的問題,分了幾個小短文分別敘述,力圖能在你的腦中勾勒出一個算法的基本概念。

排序問題

將一組已知的數據集合按照某種規則完成從無序變爲有序,這就是我們經常需要面臨的排序問題。選擇排序作爲這種問題最簡單的算法,比如有一個數組,其數據按照[6,2,5,1]排列,我們依次選擇這個數組中最大的值,從原數組刪除,然後存放到另一個數組中,那麼我們就會得到一個降序的數組[6,5,2,1]。
在這裏我們先簡單的介紹兩個概念。首先是能夠表示算法速度的大O表示法。就選擇排序這種算法,他的速度用大O表示法就是O(n2),這種表示法是表示集合的元素個數n和算法執行時間的關係。
舉個例子,數組包含元素個數爲1時,時間是0(1),數組包含元素個數爲2時,時間是O(4),而O(4)/O(1)=4纔是具有實際意義的(待排序集合爲兩個元素時算法消耗的時間是待排序集合元素爲一個時的四倍)。
其次是遞歸,簡而言之就是不斷的更新輸入參數調用自己,在每次調用的過程中判斷輸入的參數符合回退條件,符合則一層層回退並最終退出,不符合則執行遞歸條件。
我們理解遞歸,不如從函數執行的順序倒過來思考這個問題。先從輸入參數遇到回退條件的情況開始想起。舉個例子,我們需要寫一個階乘函數fn(n),我們試圖寫一個遞歸函數來解決問題。首先思考回退條件,當n=1時,fn(1)<=1,函數不需要進行任何操作,直接返回輸入值即可。第二步假設n=k時,函數返回值爲n的階乘,當輸入k+1時,我們函數需要執行(k+1)*fn(k)即可返回k+1的階乘。由數學歸納法可知,函數fn(n)在n爲任意值時都可以滿足返回的值爲輸入的階乘。

int fn(int n)
{
    if (n <= 1) return 1;

    return (n * func(n-1));
}

下面這部分Python代碼用了遞歸來實現快速排序來應對排序問題,其算法平均的時間爲O(n*log2n)。

def QuickSort(array):
    if len(array) <2:
        return array
   else:
       Pivot=array[0]
       Min=[i for i in array[1:] if i<=Pivot]
       Max=[i for i in array[1:] if i>Pivot]
       return quicksort(Min) + [Pivot] + quicksort(Max)

print QuickSort([10,5,2,3])

函數功能爲輸入一個無序數組,輸出一個有序的數組。1.函數當array<=1時,直接返回即爲有序數組。2.假設函數QuickSort(k)返回的是有序數組,當輸入QuickSort(k+1)時,設多餘元素爲r,則數組QuickSort(l)+r+QuickSort(m)爲有序數組(l數組爲k數組中比r小的數集合,m數組爲k數組中比r大數集合)。3.則函數輸入任意數組,將返回一個有序數組。
函數執行的時間與選取的Pivot這個值有莫大的關係,它關係到了整個調用調用棧的層數,如果選擇的Pivot值一直都保持輸入數組中的最小值的話,那麼層數將會爲n,那麼這個算法的操作時間將會是O(n2),如果選取的值爲數組不大不小的值,纔會是最好的情況O(n*log2n),當n足夠大的時候,這種最好的情況可以被接受爲平均的情況。

分而治之

這是書中提到的一種解決問題的思路,其類似於我們遞歸函數的思想,首先想出在什麼條件下問題是最好解決的,然後縮小問題規模,直至問題出現在我們當初找到的條件。舉個例子,需要將一塊長方形田分成數個正方形田,最大的正方向變長是多少?首先我們用最大的正方形去分割,剩下的長方形在用最大可用的正方形分割,直至最後不再有剩餘的長方形,即找到了最長的正方形變長。

查找算法

首先,待查表應該是有序的,然後找到位於表中部的元素,與待查元素作比較,小於則繼續查待查表左半部分的元素,大於則查待查表右半部分的元素。這個查詢算法每次都能排除掉待查表中一半的元素,查詢的時間是O(log2n
二叉查找樹這種數據結構將節點的左葉子存放比節點大的值,右葉子存放比節點小的值。是二分查找實際實現待查數據的數據結構。
如果你對數據庫或高級數據結構感興趣,可以研究如下數據結構:B數,紅黑樹,堆,伸展樹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章