數(shù)據(jù)結(jié)構(gòu)視頻筆記
01 緒論
”讓編程改變世界,讓我們成功吧!“ -- 小甲魚
什么是數(shù)據(jù)結(jié)構(gòu)
- 程序設(shè)計 = 數(shù)據(jù)結(jié)構(gòu) + 算法
- 關(guān)系,數(shù)據(jù)元素之間的一種或多種特定關(guān)系的集合。
邏輯結(jié)構(gòu)和物理結(jié)構(gòu)
邏輯結(jié)構(gòu):指數(shù)據(jù)對象中數(shù)據(jù)元素之間的相互關(guān)系。
物理結(jié)構(gòu):數(shù)據(jù)邏輯接哦故在計算機(jī)中的存儲形式。
四大邏輯結(jié)構(gòu):
- 集合結(jié)構(gòu):數(shù)據(jù)元素除了屬于同一個集合外沒有任何關(guān)系。
- 線性結(jié)構(gòu):數(shù)據(jù)元素是一對一的關(guān)系。
- 樹形結(jié)構(gòu):元素間一對多的層次結(jié)構(gòu)(傳銷)。
- 圖形結(jié)構(gòu):最復(fù)雜,多對多,人與人的認(rèn)識關(guān)系
物理結(jié)構(gòu):內(nèi)存的存儲方式
- 順序存儲結(jié)構(gòu):數(shù)據(jù)元素存在地址連續(xù)的存儲單元中,數(shù)據(jù)間的邏輯關(guān)系和物理關(guān)系一致。
- 鏈?zhǔn)酱鎯Y(jié)構(gòu):數(shù)據(jù)元素存放在任意的存儲單元里不需要連續(xù)。不過需要一個指針存放數(shù)據(jù)元素的地址,通過地址找到相應(yīng)的數(shù)據(jù)元素的位置,每個數(shù)據(jù)都需要跟多的空間存號碼(例子:醫(yī)院那號排隊你需要關(guān)注的前一個號)
02 算法
解決特定問題求解步驟的描述。簡化解決問題的方法、提高解決問題的速度。
五個基本特征:
- 輸入:零個也可以
- 輸出:至少一個,輸出的形式可以是打印形式,或者放回一個值
- 有窮性:
- 確定性:在一定條件下只有一條執(zhí)行路徑,相同的輸入只能有唯一的輸出結(jié)果
- 可行性:算法每一步都要可行,每一步都能通過執(zhí)行有限次數(shù)完成
算法設(shè)計的要求
- 正確性:有五個基本特征,沒有語法錯誤,合法的輸入,對于非法輸入有說明,對于刁鉆的輸入值也能有滿足要去的結(jié)果。
- 可讀性:便于閱讀、理解和交流。
- 健壯性:對于非法輸入有相應(yīng)的處理方式而不是奔潰。
- 時間效率和存儲量低:
03 時間復(fù)雜福和空間復(fù)雜度
算法效率的度量方法:
- 事后統(tǒng)計方法:設(shè)計算法測試程序和數(shù)據(jù),利用計算機(jī)計時器對不同的算法編制的程序的運行時間進(jìn)行比較。(需要事先寫好算法測試程序花費的時間和精力大)
- 事前分析估算方法:在計算機(jī)程序編寫前,依據(jù)統(tǒng)計方法對算法進(jìn)行估算。
影響算法效率:
- 算法采用的策略、方案
- 編譯產(chǎn)生的代碼質(zhì)量
- 問題的輸入規(guī)模
- 機(jī)器執(zhí)行指令的速度
分析算法的運行時間時,重要的是把基本操作的數(shù)量和輸入模式關(guān)聯(lián)起來。
函數(shù)的漸近增長:x-y函數(shù)圖 有什么有關(guān)?n的指數(shù)、
04 時間復(fù)雜度和空間復(fù)雜度2
相信你就是你想要成為的那個人
算法時間復(fù)雜度:在進(jìn)行算法分析時,語句總的執(zhí)行次數(shù)T(n)是關(guān)于問題規(guī)模n的函數(shù),進(jìn)而分析T(n)是關(guān)于問題規(guī)模的函數(shù),進(jìn)而分析T(n)隨n的變化情況并確定T(n)的數(shù)量級。n為輸入規(guī)模;T(n)=0(f(n)),表示執(zhí)行時間的增長率和f(n)的增長率相同,稱為算法的漸近時間復(fù)雜度,簡稱時間復(fù)雜度f(n)是問題規(guī)模n的某個函數(shù)。執(zhí)行次數(shù)=時間; O():大O記法。
推倒大O階方法:
- 用常數(shù)1取代運行時間中所有的加法常數(shù)。
- 在修改后的運行次數(shù)函數(shù)中,只保留高階項
- 如果最高階項存在且不是1,則去除與這個項相乘的常數(shù)
- 得到最后結(jié)果
05 時間復(fù)雜度和空間復(fù)雜度3
函數(shù)調(diào)用的時間復(fù)雜度分析:
算法的空間復(fù)雜度:
用時間復(fù)雜度來指運行時間的需求,空間復(fù)雜度指空間需求。
閏年判斷算法:
- 逐個判斷(節(jié)省空間)
- 先做個表記錄各個年份是否為閏年(節(jié)省時間)
用空間換取時間
06線性表
定義:由零個(空表)或多個數(shù)據(jù)元素組成的有限序列。排隊,線一樣的性質(zhì)結(jié)構(gòu)List:1.有順序2.只有一個直接前驅(qū)元素和直接后繼元素3.有限的
數(shù)據(jù)類型定義:是指一組形之下相同的值得集合及定義在此集合上的一些操作的總稱。
抽象數(shù)據(jù)類型ADT abstract data type:
ADT 抽象數(shù)據(jù)類型名
Data
數(shù)據(jù)元素之間邏輯關(guān)系的定義
Operation
操作
endADT
07 線性表
讓編程改變世界,讓夢想創(chuàng)造奇跡。
抽象數(shù)據(jù)類型:把數(shù)據(jù)類型和相關(guān)操作捆綁在一起。
Operation:
- InitList(*L):初始化操作,建立一個空的線性表L。
- ListEmpty(L):判斷線性表是否為空表,返回true false;
- ClearList(*L):將線性表清空;
- GetElem(L,i,*e):將線性表L中的第i個位置元素值返回給e。
- LocateElem(L,e):在線性表L中查找與給定值e相等的元素,如果查找成功返回該元素在表中的序號,否則返回0表示失敗;
- ListInsert(*L,i,e):在線性表L中第i個位置插入新元素e;
- ListDelete(*L,i,*e):刪除線性表L中第i個位置元素,并用e返回其值;
- ListLength(L):返回線性表L的元素個數(shù);
08 線性表 09 線性表
線性表的物理存儲結(jié)構(gòu):
順序存儲結(jié)構(gòu):封裝需要三個屬性:1. 數(shù)據(jù)data存儲空間的起始位置。2. 線性表的最大存儲容量MaxSize。 3. 線性表當(dāng)前長度:length。 地址計算方法:LOC(ai) = LOC(a1) + (i-1)*c T(n)=O(1)
. *獲取元素的操作:GETElem 插入操作****刪除操作
優(yōu)點:
- 無須為表示表中的元素之間的邏輯關(guān)系而增加額外的存儲空間。
- 可以快速存取表中任意位置的元素
缺點:
- 插入和刪除操作需要移動大量元素
- 當(dāng)線性表長度變化較大時,難以確定存儲空間的容量
- 容易造成存儲空間的“碎片”
鏈?zhǔn)酱鎯Y(jié)構(gòu):
特點:用一組任意的存儲單元存儲線性表的數(shù)據(jù)元素,這組存儲單元可以存在內(nèi)存中未被占用的任意位置。數(shù)據(jù)域****指針域:內(nèi)存儲的信息稱為指針或鏈。這兩部分信息組成數(shù)據(jù)元素稱為存儲映像,也稱為結(jié)點(Node)
n個結(jié)點鏈接成一個鏈表,線性表的鏈?zhǔn)酱鎯Y(jié)構(gòu)。因為此鏈表的每個結(jié)點中只包含一個指針域,所以叫單鏈表
鏈表:頭:頭指針 尾:null
10 11 12 13 線性表
頭指針:
頭指針:是指鏈表指向第一個結(jié)點的指針,若鏈表有頭結(jié)點,則是指向頭結(jié)點的指針。
頭指針具有標(biāo)識作用,所以常用頭指針冠以鏈表的名字(指針變量的名字)
無論鏈表是否為空,頭指針均不為空。
頭指針是鏈表的必要元素。
頭結(jié)點:
頭結(jié)點是為了操作的統(tǒng)一和方便而設(shè)立的,放在第一個元素的結(jié)點之前,期數(shù)據(jù)域一般無意義(但也可以用來放鏈表的長度)
有了頭結(jié)點,對子啊第一元素結(jié)點前插入結(jié)點和刪除第一結(jié)點起操作與其它結(jié)點的操作就統(tǒng)一了。
頭結(jié)點不一定是鏈表的必須要素。
單鏈表的讀取:遍歷鏈表從頭結(jié)點開始找。時間復(fù)雜度: O(n)
單鏈表的插入:只需改變地址指向
單鏈表的刪除:
上述的操作都需要先找到元素所處的位置,時間復(fù)雜度都為:O(n)
(第一部分遍歷查找第i個元素,第二部分就是實現(xiàn)插入或者刪除)和順序比沒有優(yōu)勢;
但是,要插入多個就會有差距,因為只找一次i;
單鏈表的整表創(chuàng)建
創(chuàng)建單鏈表的過程是一個動態(tài)生成鏈表的過程,從“空表”的初始狀態(tài)起,依次建立各元素結(jié)點并逐個插入鏈表。
- 頭插法建立單鏈表:把新元素放在表的第一個位置;
- 讓新結(jié)點指向頭節(jié)點
- 讓表頭的next指向新節(jié)點
- 尾插法建立單鏈表:
單鏈表的整表刪除
必須從頭開始一個一個刪除,將第一個指向第三個,去除中間的,依次下去,直到第一個指向null;
單鏈表與順序存儲結(jié)構(gòu)的優(yōu)缺點:
- 存儲分配方式:順序存儲結(jié)構(gòu)是用一段連續(xù)的存儲單元依次存儲線性表的數(shù)據(jù)元素。單鏈表采用鏈?zhǔn)酱鎯Y(jié)構(gòu),用一組任意的存儲單元存放線性表的元素。
- 時間性能:
- 查找: 順序:O(1) 單鏈表:O(n)
- 插入刪除:順序:O(n) 單鏈表:計算出位置后:O(1)
- 空間性能:順序存儲結(jié)構(gòu)需要預(yù)分存儲空間,分大了浪費,分小了容易溢出。單鏈表:不需要提前分配空間,元素個數(shù)也不受限制。
14 線性表
靜態(tài)鏈表
用數(shù)組描述的鏈表叫做靜態(tài)鏈表;
- 對數(shù)值的第一個和最后一個元素做特殊處理,他們的date不存放數(shù)據(jù)。
- 通常把未使用的數(shù)組元素稱為備用鏈表
- 數(shù)組的第一個元素,即下標(biāo)為0的元素的cur就存放備用鏈表的第一個結(jié)點的下標(biāo)
- 數(shù)組的最后一個元素,即小標(biāo)為MAXSIZE-1的cur則存放第一個有數(shù)值的元素的下標(biāo),相當(dāng)于單鏈表中的頭結(jié)點作用。
1
2
17 線性表
循環(huán)鏈表
繞
單鏈表:不從頭節(jié)點出發(fā)就不能訪問到全部的節(jié)點。
循環(huán)鏈表:將單鏈表中終端結(jié)點的指針端由空指針改為指向頭結(jié)點,使整個單鏈表形成一個環(huán),單循環(huán)鏈表。
區(qū)別:判斷空表方法:
- 單鏈表:head->next是否為null
- 循環(huán)鏈表:head->next是否等于head
18 約瑟夫問題
猶太歷史學(xué)家Josephus的故事:在羅馬人占領(lǐng)喬塔帕特后,38個猶太人與Josephus及他的朋友躲在山洞中,39個猶太人決定寧愿死也不要被敵人抓到,于是決定了自殺的方式,41個人排成一個圓圈,由第一個人開始報數(shù),每報道第3個人該人就必須自殺,然后由下一個重新報數(shù),直到左右人死亡為止。
然而Josephus和他的朋友并不想遵從,于是Josephus將朋友和自己安排在16和31的位置,逃過了這場死亡游戲
編程:利用程序把41個人自殺的順序編號輸出
視頻上還有一道題。
19 線性表
循環(huán)鏈表的特點
訪問最后一個結(jié)點:
- 單鏈表需要O(n)
-
循環(huán)鏈表需要O(1):對循環(huán)鏈表進(jìn)行一個小的改變
這時判斷鏈表為空的方法:rear是否等于rear->next
特點:無須增加存儲量,僅對鏈表方式稍作改變,即可使得表處理更加方便靈活。
例題:實現(xiàn)將兩個線性表(a1,a2,a3,...an)和(b1,b2,b3,b4...,bn)連接成一個線性表(a1,a2,...an,b1,b2...bn)
分析:
1. 如果是單鏈表就需要遍歷第一個鏈表找到an,然后把結(jié)點b1鏈到an的后面,時間復(fù)雜度是:O(n);
2. 尾指針表示的單循環(huán)鏈表,只需修改指針,無須遍歷,O(1)
例題二:判斷單鏈表中是否有環(huán)
有環(huán)定義:鏈表的尾節(jié)點指向了鏈表中的某個節(jié)點。
判斷方法:
- 使用p、q指針,p向前走一次走一步,q向前走每次從頭開始走,判斷p,q的步數(shù)是否相等。
- 快慢指針,p走一步,q走兩步,如果q=p則有環(huán)