python structure_GitHub - CYZYZG/Data_Structure_with_Python: 这是我在学习《基于Python的数据结构》的时候的笔记与代码...
Data_Structure_with_Python
這是我在學(xué)習(xí)《基于Python的數(shù)據(jù)結(jié)構(gòu)》的時(shí)候的筆記與代碼
主要參考:數(shù)據(jù)結(jié)構(gòu)與算法(Python)
對(duì)于算法的時(shí)間效率,我們可以用“大O記法”來(lái)表示。
“大O記法”:對(duì)于單調(diào)的整數(shù)函數(shù)f,如果存在一個(gè)整數(shù)函數(shù)g和實(shí)常數(shù)c>0,使得對(duì)于充分大的n總有f(n)<=c*g(n),就說(shuō)函數(shù)g是f的一個(gè)漸近函數(shù)(忽略常數(shù)),記為f(n)=O(g(n))。也就是說(shuō),在趨向無(wú)窮的極限意義下,函數(shù)f的增長(zhǎng)速度受到函數(shù)g的約束,亦即函數(shù)f與函數(shù)g的特征相似。
時(shí)間復(fù)雜度:假設(shè)存在函數(shù)g,使得算法A處理規(guī)模為n的問(wèn)題示例所用時(shí)間為T(n)=O(g(n)),則稱O(g(n))為算法A的漸近時(shí)間復(fù)雜度,簡(jiǎn)稱時(shí)間復(fù)雜度,記為T(n)
最壞時(shí)間復(fù)雜度
算法完成工作最多需要多少基本操作,即最壞時(shí)間復(fù)雜度
時(shí)間復(fù)雜度的幾條基本計(jì)算規(guī)則
基本操作,即只有常數(shù)項(xiàng),認(rèn)為其時(shí)間復(fù)雜度為O(1)
順序結(jié)構(gòu),時(shí)間復(fù)雜度按加法進(jìn)行計(jì)算
循環(huán)結(jié)構(gòu),時(shí)間復(fù)雜度按乘法進(jìn)行計(jì)算
分支結(jié)構(gòu),時(shí)間復(fù)雜度取最大值
判斷一個(gè)算法的效率時(shí),往往只需要關(guān)注操作數(shù)量的最高次項(xiàng),其它次要項(xiàng)和常數(shù)項(xiàng)可以忽略
在沒(méi)有特殊說(shuō)明時(shí),我們所分析的算法的時(shí)間復(fù)雜度都是指最壞時(shí)間復(fù)雜度
常見(jiàn)時(shí)間復(fù)雜度
常見(jiàn)時(shí)間復(fù)雜度之間的關(guān)系
timeit模塊
timeit模塊可以用來(lái)測(cè)試一小段Python代碼的執(zhí)行速度。
class timeit.Timer(stmt='pass', setup='pass', timer=)
Timer是測(cè)量小段代碼執(zhí)行速度的類。
stmt參數(shù)是要測(cè)試的代碼語(yǔ)句(statment);
setup參數(shù)是運(yùn)行代碼時(shí)需要的設(shè)置;
timer參數(shù)是一個(gè)定時(shí)器函數(shù),與平臺(tái)有關(guān)。
timeit.Timer.timeit(number=1000000)
Timer類中測(cè)試語(yǔ)句執(zhí)行速度的對(duì)象方法。number參數(shù)是測(cè)試代碼時(shí)的測(cè)試次數(shù),默認(rèn)為1000000次。方法返回執(zhí)行代碼的平均耗時(shí),一個(gè)float類型的秒數(shù)。
list內(nèi)置操作的時(shí)間復(fù)雜度
dict內(nèi)置操作的時(shí)間復(fù)雜度
Python的內(nèi)置數(shù)據(jù)結(jié)構(gòu)
Python給我們提供了很多現(xiàn)成的數(shù)據(jù)結(jié)構(gòu)類型,這些系統(tǒng)自己定義好的,不需要我們自己去定義的數(shù)據(jù)結(jié)構(gòu)叫做Python的內(nèi)置數(shù)據(jù)結(jié)構(gòu),比如列表、元組、字典。
Python的擴(kuò)展數(shù)據(jù)結(jié)構(gòu)
而有些數(shù)據(jù)組織方式,Python系統(tǒng)里面沒(méi)有直接定義,需要我們自己去定義實(shí)現(xiàn)這些數(shù)據(jù)的組織方式,這些數(shù)據(jù)組織方式稱之為Python的擴(kuò)展數(shù)據(jù)結(jié)構(gòu),比如棧,隊(duì)列等。
算法與數(shù)據(jù)結(jié)構(gòu)的區(qū)別
數(shù)據(jù)結(jié)構(gòu)只是靜態(tài)的描述了數(shù)據(jù)元素之間的關(guān)系。
高效的程序需要在數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ)上設(shè)計(jì)和選擇算法。
程序 = 數(shù)據(jù)結(jié)構(gòu) + 算法
總結(jié):算法是為了解決實(shí)際問(wèn)題而設(shè)計(jì)的,數(shù)據(jù)結(jié)構(gòu)是算法需要處理的問(wèn)題載體
抽象數(shù)據(jù)類型(Abstract Data Type)
抽象數(shù)據(jù)類型(ADT)的含義是指一個(gè)數(shù)學(xué)模型以及定義在此數(shù)學(xué)模型上的一組操作。即把數(shù)據(jù)類型和數(shù)據(jù)類型上的運(yùn)算捆在一起,進(jìn)行封裝。引入抽象數(shù)據(jù)類型的目的是把數(shù)據(jù)類型的表示和數(shù)據(jù)類型上運(yùn)算的實(shí)現(xiàn)與這些數(shù)據(jù)類型和運(yùn)算在程序中的引用隔開(kāi),使它們相互獨(dú)立。
最常用的數(shù)據(jù)運(yùn)算有五種:
插入
刪除
修改
查找
排序
線性表
一個(gè)線性表是某類元素的一個(gè)集合,還記錄著元素之間的一種順序關(guān)系。
根據(jù)線性表的實(shí)際存儲(chǔ)方式,分為兩種實(shí)現(xiàn)模型:
順序表,將元素順序地存放在一塊連續(xù)的存儲(chǔ)區(qū)里,元素間的順序關(guān)系由它們的存儲(chǔ)順序自然表示。
鏈表,將元素存放在通過(guò)鏈接構(gòu)造起來(lái)的一系列存儲(chǔ)塊中。
順序表的兩種存儲(chǔ)方式:
元素內(nèi)置(一體式結(jié)構(gòu)):表里存儲(chǔ)的元素大小固定
元素外置(分離式結(jié)構(gòu)):表里只存儲(chǔ)鏈接
表中存儲(chǔ)的兩個(gè)信息
1.表中的元素集合
2.信息主要包括元素存儲(chǔ)區(qū)的容量和當(dāng)前表中已有的元素個(gè)數(shù)兩項(xiàng)
增加元素
a. 尾端加入元素,時(shí)間復(fù)雜度為O(1)
b. 中間插入,時(shí)間復(fù)雜度為O(n)
刪除元素
a. 刪除表尾元素,時(shí)間復(fù)雜度為O(1)
b. 中間元素刪除,時(shí)間復(fù)雜度為O(n)
Python中的順序表
list和tuple
tuple是不可變類型,即不變的順序表,因此不支持改變其內(nèi)部狀態(tài)的任何操作,而其他方面,則與list的性質(zhì)類似。
list就是一種采用分離式技術(shù)實(shí)現(xiàn)的動(dòng)態(tài)順序表。
鏈表與順序表的對(duì)比
鏈表失去了順序表隨機(jī)讀取的優(yōu)點(diǎn),同時(shí)鏈表由于增加了結(jié)點(diǎn)的指針域,空間開(kāi)銷比較大,但對(duì)存儲(chǔ)空間的使用要相對(duì)靈活。
鏈表與順序表的各種操作復(fù)雜度如下所示:
鏈表的主要耗時(shí)操作是遍歷查找
順序表查找很快,主要耗時(shí)的操作是拷貝覆蓋
3.棧
4.隊(duì)列
代碼:
排序算法(Sorting Algorithm):是一種能將一串?dāng)?shù)據(jù)按照特定順序進(jìn)行排列的一種算法。
穩(wěn)定性
穩(wěn)定性:穩(wěn)定排序算法會(huì)讓原本有相等鍵值的紀(jì)錄維持相對(duì)次序。也就是如果一個(gè)排序算法是穩(wěn)定的,當(dāng)有兩個(gè)相等鍵值的紀(jì)錄R和S,且在原本的列表中R出現(xiàn)在S之前,在排序過(guò)的列表中R也將會(huì)是在S之前。
當(dāng)相等的元素是無(wú)法分辨的,比如像是整數(shù),穩(wěn)定性并不是一個(gè)問(wèn)題。然而,假設(shè)以下的數(shù)對(duì)將要以他們的第一個(gè)數(shù)字來(lái)排序。
(4, 1) (3, 1) (3, 7)(5, 6)
在這個(gè)狀況下,有可能產(chǎn)生兩種不同的結(jié)果,一個(gè)是讓相等鍵值的紀(jì)錄維持相對(duì)的次序,而另外一個(gè)則沒(méi)有:
(3, 1) (3, 7) (4, 1) (5, 6) (維持次序)
(3, 7) (3, 1) (4, 1) (5, 6) (次序被改變)
不穩(wěn)定排序算法可能會(huì)在相等的鍵值中改變紀(jì)錄的相對(duì)次序,但是穩(wěn)定排序算法從來(lái)不會(huì)如此。不穩(wěn)定排序算法可以被特別地實(shí)現(xiàn)為穩(wěn)定。作這件事情的一個(gè)方式是人工擴(kuò)充鍵值的比較,如此在其他方面相同鍵值的兩個(gè)對(duì)象間之比較,(比如上面的比較中加入第二個(gè)標(biāo)準(zhǔn):第二個(gè)鍵值的大小)就會(huì)被決定使用在原先數(shù)據(jù)次序中的條目,當(dāng)作一個(gè)同分決賽。然而,要記住這種次序通常牽涉到額外的空間負(fù)擔(dān)。
常見(jiàn)排序算法效率比較
代碼:
希爾排序(Shell Sort)是插入排序的一種。也稱縮小增量排序,是直接插入排序算法的一種更高效的改進(jìn)版本。希爾排序是非穩(wěn)定排序算法。
希爾排序過(guò)程
希爾排序的基本思想是:將數(shù)組列在一個(gè)表中并對(duì)列分別進(jìn)行插入排序,重復(fù)這過(guò)程,不過(guò)每次用更長(zhǎng)的列(步長(zhǎng)更長(zhǎng)了,列數(shù)更少了)來(lái)進(jìn)行。最后整個(gè)表就只有一列了。將數(shù)組轉(zhuǎn)換至表是為了更好地理解這算法,算法本身還是使用數(shù)組進(jìn)行排序。
例如,假設(shè)有這樣一組數(shù)[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我們以步長(zhǎng)為5開(kāi)始進(jìn)行排序,我們可以通過(guò)將這列表放在有5列的表中來(lái)更好地描述算法,這樣他們就應(yīng)該看起來(lái)是這樣(豎著的元素是步長(zhǎng)組成):
13 14 94 33 82
25 59 94 65 23
45 27 73 25 39
10
然后我們對(duì)每列進(jìn)行排序:
10 14 73 25 23
13 27 94 33 39
25 59 94 65 82
45
將上述四行數(shù)字,依序接在一起時(shí)我們得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ]。這時(shí)10已經(jīng)移至正確位置了,然后再以3為步長(zhǎng)進(jìn)行排序:
10 14 73
25 23 13
27 94 33
39 25 59
94 65 82
45
排序之后變?yōu)?#xff1a;
10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94
最后以1步長(zhǎng)進(jìn)行排序(此時(shí)就是簡(jiǎn)單的插入排序了)
6.二分查找
樹(shù)(英語(yǔ):tree)是一種抽象數(shù)據(jù)類型(ADT)
樹(shù)的術(shù)語(yǔ)
節(jié)點(diǎn)的度:一個(gè)節(jié)點(diǎn)含有的子樹(shù)的個(gè)數(shù)稱為該節(jié)點(diǎn)的度;
樹(shù)的度:一顆樹(shù)中,最大的節(jié)點(diǎn)的度稱為樹(shù)的度;
葉節(jié)點(diǎn)或終端節(jié)點(diǎn):度為零的節(jié)點(diǎn);
父節(jié)點(diǎn):若一個(gè)節(jié)點(diǎn)含有子節(jié)點(diǎn),則這個(gè)節(jié)點(diǎn)稱為其子節(jié)點(diǎn)的父節(jié)點(diǎn);
子節(jié)點(diǎn):一個(gè)節(jié)點(diǎn)含有的子樹(shù)的根節(jié)點(diǎn)稱為該節(jié)點(diǎn)的子節(jié)點(diǎn);
兄弟節(jié)點(diǎn):具有相同父節(jié)點(diǎn)的節(jié)點(diǎn)互相稱為兄弟節(jié)點(diǎn);
節(jié)點(diǎn)的層次:從根節(jié)點(diǎn)開(kāi)始定義起,根為第一層,根的子節(jié)點(diǎn)為第二層,以此類推;
樹(shù)的高度或深度:樹(shù)中節(jié)點(diǎn)的最大層次;
堂兄弟節(jié)點(diǎn):父節(jié)點(diǎn)在同一層次的節(jié)點(diǎn)互為堂兄弟;
節(jié)點(diǎn)的祖先:從根節(jié)點(diǎn)到該節(jié)點(diǎn)所經(jīng)分支上的所有節(jié)點(diǎn);
子孫:以某一節(jié)點(diǎn)為根的子樹(shù)中任一節(jié)點(diǎn)都稱為該節(jié)點(diǎn)的子孫;
森林:由m(m >= 0)顆互不相交的樹(shù)的集合稱為森林;
樹(shù)的種類
無(wú)序樹(shù):樹(shù)中任意節(jié)點(diǎn)的子節(jié)點(diǎn)之間沒(méi)有順序關(guān)系
有序樹(shù):樹(shù)中任意節(jié)點(diǎn)的子節(jié)點(diǎn)之間有順序關(guān)系
二叉樹(shù):每個(gè)節(jié)點(diǎn)最多含有兩個(gè)子樹(shù)
完全二叉樹(shù):除最底層最后一個(gè)外其他必須有子樹(shù)
滿二叉樹(shù):所有葉節(jié)點(diǎn)都在最底層的完全二叉樹(shù)
平衡二叉樹(shù):當(dāng)且僅當(dāng)任何節(jié)點(diǎn)的兩顆子樹(shù)的高度差不大于1的二叉樹(shù)
排序二叉樹(shù):二叉搜索樹(shù)
霍夫曼樹(shù)(用于信息編碼):帶權(quán)路徑最短的二叉樹(shù)
B樹(shù):一種對(duì)讀寫操作進(jìn)行優(yōu)化的自平衡的二叉查找樹(shù),能夠保持?jǐn)?shù)據(jù)有序,擁有杜宇兩個(gè)子樹(shù)
常見(jiàn)的一些樹(shù)的應(yīng)用場(chǎng)景
1.xml,html等,那么編寫這些東西的解析器的時(shí)候,不可避免用到樹(shù)
2.路由協(xié)議就是使用了樹(shù)的算法
3.mysql數(shù)據(jù)庫(kù)索引
4.文件系統(tǒng)的目錄結(jié)構(gòu)
5.所以很多經(jīng)典的AI算法其實(shí)都是樹(shù)搜索,此外機(jī)器學(xué)習(xí)中的decision tree也是樹(shù)結(jié)構(gòu)
二叉樹(shù)的遍歷
深度優(yōu)先遍歷和廣度優(yōu)先遍歷
深度優(yōu)先一般用遞歸,廣度優(yōu)先一般用隊(duì)列。一般情況下能用遞歸實(shí)現(xiàn)的算法大部分也能用堆棧來(lái)實(shí)現(xiàn)。
深度優(yōu)先遍歷
先序遍歷 在先序遍歷中,我們先訪問(wèn)根節(jié)點(diǎn),然后遞歸使用先序遍歷訪問(wèn)左子樹(shù),再遞歸使用先序遍歷訪問(wèn)右子樹(shù)
根節(jié)點(diǎn)->左子樹(shù)->右子樹(shù)
def preorder(self, root):
"""遞歸實(shí)現(xiàn)先序遍歷"""
if root == None:
return
print root.elem
self.preorder(root.lchild)
self.preorder(root.rchild)
中序遍歷 在中序遍歷中,我們遞歸使用中序遍歷訪問(wèn)左子樹(shù),然后訪問(wèn)根節(jié)點(diǎn),最后再遞歸使用中序遍歷訪問(wèn)右子樹(shù)
左子樹(shù)->根節(jié)點(diǎn)->右子樹(shù)
def inorder(self, root):
"""遞歸實(shí)現(xiàn)中序遍歷"""
if root == None:
return
self.inorder(root.lchild)
print root.elem
self.inorder(root.rchild)
后序遍歷 在后序遍歷中,我們先遞歸使用后序遍歷訪問(wèn)左子樹(shù)和右子樹(shù),最后訪問(wèn)根節(jié)點(diǎn)
左子樹(shù)->右子樹(shù)->根節(jié)點(diǎn)
def postorder(self, root):
"""遞歸實(shí)現(xiàn)后續(xù)遍歷"""
if root == None:
return
self.postorder(root.lchild)
self.postorder(root.rchild)
print root.elem
前序和后序在本質(zhì)上都是將父節(jié)點(diǎn)與子結(jié)點(diǎn)進(jìn)行分離,但并沒(méi)有指明左子樹(shù)和右子樹(shù)的能力,因此得到這兩個(gè)序列只能明確父子關(guān)系,而不能確定一個(gè)二叉樹(shù)。
由二叉樹(shù)的中序和前序遍歷序列可以唯一確定一棵二叉樹(shù) ,由前序和后序遍歷則不能唯一確定一棵二叉樹(shù)
由二叉樹(shù)的中序和后序遍歷序列可以唯一確定一棵二叉樹(shù),由前序和后序遍歷則不能唯一確定一棵二叉樹(shù)
總結(jié)
以上是生活随笔為你收集整理的python structure_GitHub - CYZYZG/Data_Structure_with_Python: 这是我在学习《基于Python的数据结构》的时候的笔记与代码...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python的装饰器迭代器与生成器_py
- 下一篇: java ltpa_LTPA Cooki