1. 程式人生 > >Python 第八階段 學習記錄之---算法

Python 第八階段 學習記錄之---算法

第一個元素 排序 小根堆 () 規律 空間復雜度 場景 復數 練習

算法(Algorithm): 一個計算過程, 解決問題的方法

1、遞歸的兩個特點
- 調用自身
- 結束條件

時間復雜度
- 時間復雜度是用來估計算法運行時間的一個式子(單位)
- 一般來說,時間復雜度高的算法比復雜度低的算法快
空間復雜度
用來評估算法內存占用大小的一個式子

列表查找: 從列表中查找指定元素
輸入:無序
輸出:有序
順序查找:
從列表第一個元素開始,順序進行搜索,直到找到為止。

二分查找:
從有序列表的候選區data[0:n]開始,通過對待查找的值與候選區中間值的比較,可以使候選區減少一半。
找任何一個數,次數都不會超過LOG 2 N, 2為底N的對數, 2 ** x <= n
在10**5內找一個數,那麽找到它,需要找的次數 2 **x < 10**5, x = 16

列表排序:

列表排序: 將無序列表變為有序列表
應用場景:
各種榜單、表格、給二分排序用,給其它算法用

排序lowB三人組:
冒泡排序
選擇排序
插入排序
快速排序
排序NB二人組:
- 堆排序
- 歸並排序
沒什麽人用的排序:
基數排序
希爾排序
桶排序


一、LOW
時間復雜度:O(n**2)
空間復雜度:O(1)

冒泡排序:
時間復雜度:O(n**2)
random.shuffle(data) #
排序一萬個數得10多秒,
首先,列表每兩個相鄰的數,如果前邊的比後邊的大,那麽交換這兩個數
如果冒泡排序中執行一趟而沒有交換,則列表已經是有序狀態,可以直接結束算法。
選擇排序
一趟遍歷記錄最小的數,放到第一個位置;
再一趟遍歷記錄剩余列表中最小的數,繼續放置;
找到最小的數:
if xx < xxx: xxx=xx, xx,xx=xx,xx, 小於則交換
插入排序:(打牌一樣,來一個數、插入一次)
列表被分為有序區和無序區兩個部份。最初有序區只有一個元素。
每次從無序區選擇一個元素,插入到有序區的位置,直到無序區變空。


二、快排(快速排序)
快速排序:
好寫的排序算法裏最快的
快的排序裏最好寫的

快排思路:
取一個元素P(第一個元素), 使P歸位;
列表被P分成兩部分,左邊都比P小,右邊都比P大;
遞歸完成排序

效率:
快排相比冒泡快了多少?
問題:
最壞情況
遞歸

最好情況 一般情況 最壞情況
快排 O(nlogn) O(nlogn) O(n^2)
冒泡 O(n) O(n^2) O(n^2)

代碼實現:



樹是一種數據結構 比如:目錄結構
樹是一種可以遞歸定義的數據結構
樹是由n個節點組成的集合:
如果n=0,那這是一棵空樹;
如果n>0,那存在1個節點作為樹的根節點,其他節點可以分為m個集合,每個集合本身又是一棵樹。
一些概念
根節點、葉子節點
樹的深度(高度)
樹的度: 有幾個子結點(下一層,)
孩子節點/父節點
子樹

二叉樹:度不超過2的樹(節點最多有兩個叉)
滿二叉樹
完全二叉樹

二叉樹的存儲方式:
鏈式存儲方式
順序存儲方式(列表)

父節點和左孩子節點的編號下標有什麽關系?
i -> 2*i + 1

父節點和右孩子節點的編號下標有什麽關系?
i -> 2i+2
比如,我們要找根節點左孩子的左孩子
x = 2*(2*0+1)+1 = 3, list_[3]
最後一個有子結點的堆
x = n // 2 - 1 # n = len()

二叉樹是度不超過2的樹
滿二叉樹與完全二叉樹
(完全)二叉樹可以用列表來存儲,通過規律可以從父親找到孩子或從孩子找到父親


大根堆:一棵完全二叉樹,滿足任一節點都比其孩子節點大
小根堆:一棵完全二叉樹,滿足任一節點都比其孩子節點小

假設:節點的左右子樹都是堆,但自身不是堆
當根節點的左右子樹都是堆時,可以通過一次向下的調整來將其變換成一個堆
堆排序過程:
建立堆
得到堆頂元素,為最大元素
去掉堆頂,將堆最後一個元素放到堆頂,此時可通過一次調整重新使堆有序。
堆頂元素為第二大元素。
重復步驟3,直到堆變空。



歸並:
- 假設現在的列表分成兩段有序, 如何將其合成為一個有序列表
- 從兩邊分別取,取最小的 ===> 這個過程就叫歸並
肯定有一邊先取完,剩下的就不必再比較,直接取下來,xx[:] = xxx[:]

有了歸並如何使用?
分解: 將列表越分越小,直至分成一個元素。
一個元素是有序的
合並: 將兩個有序列表歸並,列表越來越大。


時間復雜度:O(nlogn)
空間復雜度:O(n)

* 三種排序算法的時間復雜度是O(nlogn)
- 一般情況下,就運行時間而言:
快速排序 < 歸並排序 < 堆排序

- 三種排序算法的缺點:
- 快速排序: 極端情況下排序效率底
- 歸並排序: 需要額外的內存開銷
- 堆排序: 在快的排序算法中相對較慢

希爾排序:
希爾排序是一種分組插入排序算法。
首先取一個整數d1=n/2,將元素分為d1個組,每組相鄰量元素之間距離為d1,在各組內進行直接插入排序;
取第二個整數d2=d1/2,重復上述分組排序過程,直到di=1,即所有元素在同一組內進行直接插入排序。
希爾排序每趟並不使某些元素有序,而是使整體數據越來越接近有序;最後一趟排序使得所有數據有序。

時間復雜度: O((1+T)n) # O(1.3n)

排序:
- 兩個排序條件
姓名、年齡
排序的穩定性,


冒泡、快排、堆、歸並
算法穩定性:
就是算法的穩定性:假定在待排序的記錄序列中,存在多個具有相同的關鍵字的記錄(有相同的元素),
若經過排序,這些記錄的相對次序保持不變,
即在原序列中,ri=rj,且ri在rj之前,而在排序後的序列中,ri仍在rj之前,則稱這種排序算法是穩定的;否則稱為不穩定的。

練習1:
1、現在有一個列表,列表中的數範圍都在0到100之間,列表長度大約為100萬,設計算法在O(n)時間復雜度內將列表進行排序。
- 計數排序,統計每個數出現的次數。只能是數值型,然後再寫回列表
這時使用快排等會比較慢,有大量重復數據

2、有N(n>1000000)個數,如何取出最大的前10個數?
- 取列表前10個元素建立一個小根堆。堆頂就是目前第10大的數
- 依次向後遍歷原列表,對於列表中的元素,如果小於堆頂,則忽略該元素;如果大於堆頂,則將堆頂更換為該元素,並且對堆進行一次調整;
- 遍歷列表所有元素後,倒序彈出堆頂。


堆----> 優先排列
練習2:
給定一個升序列表和一個整數,返回該整數在列表中的下標範圍。
例如: 列表[1,2,3,3,3,4,4,5], 若查找3,則返回(2,4);若查找0,由返回(0,0)



























Python 第八階段 學習記錄之---算法