1. 程式人生 > 其它 >資料結構及演算法(演算法篇)

資料結構及演算法(演算法篇)

工作之餘b站充電 視訊連結:https://www.bilibili.com/video/BV1iJ411E7xW?from=search&seid=11746233105888556082

課程介紹

1.1課程目標 資料結構和演算法這門課程無論在哪個學校的計算機專業,都是一門必修課,因為這門課程非常重要的,是程式設計必備 的基礎,但是這門課程是一門不太好學習的課程,因為它學習起來是非常的枯燥乏味的。但是如果你想讓自己的編 程能力有質的飛躍,不再停留於呼叫現成的API,而是追求更完美的實現,那麼這門課程就是你的必修課,因為程 序設計=資料結構+演算法。 通過對基礎資料結構和演算法的學習,能更深層次的理解程式,提升編寫程式碼的能力,讓程式的程式碼更優雅,效能更 高。 1.2 課程內容 1.資料結構和演算法概述 2.演算法分析 3.排序 4.線性表 5.符號表 6.樹 7.堆 8.優先佇列 9.並查集 10.圖l

一、資料結構和演算法概述

1.1什麼是資料結構?

官方解釋: 資料結構是一門研究非數值計算的程式設計問題中的操作物件,以及他們之間的關係和操作等相關問題的學科。 大白話: 資料結構就是把資料元素按照一定的關係組織起來的集合,用來組織和儲存資料

1.2資料結構分類

傳統上,我們可以把資料結構分為邏輯結構和物理結構兩大類。 邏輯結構分類: 邏輯結構是從具體問題中抽象出來的模型,是抽象意義上的結構,按照物件中資料元素之間的相互關係分類,也是 我們後面課題中需要關注和討論的問題。 a.集合結構:集合結構中資料元素除了屬於同一個集合外,他們之間沒有任何其他的關係。      b.線性結構:線性結構中的資料元素之間存在一對一的關係 c.樹形結構:樹形結構中的資料元素之間存在一對多的層次關係 d.圖形結構:圖形結構的資料元素是多對多的關係      物理結構分類:
邏輯結構在計算機中真正的表示方式(又稱為映像)稱為物理結構,也可以叫做儲存結構。常見的物理結構有順序 儲存結構、鏈式儲存結構。 順序儲存結構: 把資料元素放到地址連續的儲存單元裡面,其資料間的邏輯關係和物理關係是一致的 ,比如我們常用的陣列就是 順序儲存結構。   順序儲存結構存在一定的弊端,就像生活中排時也會有人插隊也可能有人有特殊情況突然離開,這時候整個結構都 處於變化中,此時就需要鏈式儲存結構。 鏈式儲存結構:   是把資料元素存放在任意的儲存單元裡面,這組儲存單元可以是連續的也可以是不連續的。此時,資料元素之間並 不能反映元素間的邏輯關係,因此在鏈式儲存結構中引進了一個指標存放資料元素的地址,這樣通過地址就可以找 到相關聯資料元素的位置         

1.3什麼是演算法?

官方解釋: 演算法是指解題方案的準確而完整的描述,是一系列解決問題的清晰指令,演算法代表著用系統的方法解決問題的策略 機制。也就是說,能夠對一定規範的輸入,在有限時間內獲得所要求的輸出。 大白話: 根據一定的條件,對一些資料進行計算,得到需要的結果。

1.4演算法初體驗

在生活中,我們如果遇到某個問題,常常解決方案不是唯一的。 例如從西安到北京,如何去?會有不同的解決方案,我們可以坐飛機,可以坐火車,可以坐汽車,甚至可以步行, 不同的解決方案帶來的時間成本和金錢成本是不一樣的,比如坐飛機用的時間最少,但是費用最高,步行費用最 低,但時間最長。 再例如在北京二環內買一套四合院,如何付款?也會有不同的解決方案,可以一次性現金付清,也可以通過銀行做 按揭。這兩種解決方案帶來的成本也不一樣,一次性付清,雖然當時出的錢多,壓力大,但是沒有利息,按揭雖然 當時出的錢少,壓力比較小,但是會有利息,而且30年的總利息幾乎是貸款額度的一倍,需要多付錢。 在程式中,我們也可以用不同的演算法解決相同的問題,而不同的演算法的成本也是不相同的。總體上,一個優秀的算 法追求以下兩個目標: 1.花最少的時間完成需求; 2.佔用最少的記憶體空間完成需求; 下面我們用一些實際案例體驗一些演算法。 需求1: 計算1到100的和。 第一種解法: public static void main(String[] args) { int sum = 0; int n=100; for (int i = 1; i <= n; i++) { sum += i; } System.out.println("sum=" + sum); } 第二種解法: public static void main(String[] args) { int sum = 0; int n=100; sum = (n+1)*n/2; System.out.println("sum="+sum); } 第一種解法要完成需求,要完成以下幾個動作: 1.定義兩個整型變數; 2.執行100次加法運算; 3.列印結果到控制檯; 第二種解法要完成需求,要完成以下幾個動作: 1.定義兩個整型變數; 2.執行1次加法運算,1次乘法運算,一次除法運算,總共3次運算; 3.列印結果到控制檯; 很明顯,第二種演算法完成需求,花費的時間更少一些。 需求2: 計算10的階乘 第一種解法: public class Test { public static void main(String[] args) { //測試,計算10的階乘 long result = fun1(10); System.out.println(result); } //計算n的階乘 public static long fun1(long n){ if (n==1){ return 1; } return n*fun1(n-1); } } 第二種解法: public class Test { public static void main(String[] args) { //測試,計算10的階乘 long result = fun2(10); System.out.println(result); } //計算n的階乘 public static long fun2(long n){ int result=1; for (long i = 1; i <= n; i++) { result*=i; } return result; } }   第一種解法,使用遞迴完成需求,fun1方法會執行10次,並且第一次執行未完畢,呼叫第二次執行,第二次執行 未完畢,呼叫第三次執行...最終,最多的時候,需要在棧記憶體同時開闢10塊記憶體分別執行10個fun1方法。 第二種解法,使用for迴圈完成需求,fun2方法只會執行一次,最終,只需要在棧記憶體開闢一塊記憶體執行fun2方法 即可。   很明顯,第二種演算法完成需求,佔用的記憶體空間更小。

一、演算法分析

前面我們已經介紹了,研究演算法的最終目的就是如何花更少的時間,如何佔用更少的記憶體去完成相同的需求,並且 也通過案例演示了不同演算法之間時間耗費和空間耗費上的差異,但我們並不能將時間佔用和空間佔用量化,因此, 接下來我們要學習有關演算法時間耗費和演算法空間耗費的描述和分析。有關演算法時間耗費分析,我們稱之為演算法的時 間複雜度分析,有關演算法的空間耗費分析,我們稱之為演算法的空間複雜度分析。

1.1演算法的時間複雜度分析

我們要計算演算法時間耗費情況,首先我們得度量演算法的執行時間,那麼如何度量呢? 事後分析估算方法: 比較容易想到的方法就是我們把演算法執行若干次,然後拿個計時器在旁邊計時,這種事後統計的方法看上去的確不 錯,並且也並非要我們真的拿個計算器在旁邊計算,因為計算機都提供了計時的功能。這種統計方法主要是通過設 計好的測試程式和測試資料,利用計算機計時器對不同的演算法編制的程式的執行時間進行比較,從而確定演算法效率 的高低,但是這種方法有很大的缺陷:必須依據演算法實現編制好的測試程式,通常要花費大量時間和精力,測試完 瞭如果發現測試的是非常糟糕的演算法,那麼之前所做的事情就全部白費了,並且不同的測試環境(硬體環境)的差別 導致測試的結果差異也很大。 個人學習筆記,記錄日常學習,便於查閱及加深,僅為方便個人使用。