由於圖片看不了,大家可以看這個百度雲筆記,我看完大話數據結構整理的,裏面有些內容我還不太明白,等過段時間還需要仔細回顧回顧。點擊打開鏈接
一.數據及數據結構的基本概念
- 數據結構是一門研究非數值計算的程序設計問題中的操作對象,以及他們之間的關係和操作等相關問題的學科。
- 數據:符號集合
- 數據元素:組成數據有一定意義的基本單位,也被稱作記錄。
- 數據項:一個數據元素可以由多個數據項組成,是數據不可分割的最小單位。
- 數據對象:是性質相同的數據元素的集合,是數據的子集。
2.數據結構:數據元素的特定關係。
- 邏輯結構:數據元素之間的相關關係
集合關係:同屬一個集合,沒有其他關係
線性結構:數據元素之間是一對一的關係
2.物理結構:數據的邏輯結構在計算機中的存儲形式
3.數據類型:是指一組性質相同的值的集合,以及此集合上的一些操作。
原子類型:不可以分割的基本類型:整形。。。
結構類型:若干個類型組合,可以分割,比如:數組
二、算法
指令的有限序列,每條指令表示一個或多個操作。
1.算法的基本特性:
輸入、輸出、有窮性、確定性、可行性
2.算法的設計要求:
正確性、可讀性、健壯性、高效率和低存儲量
事後統計方法(不科學,不精確)
3.事前估算方法:時間複雜度,用O()表示——大O記法
空間複雜度(用空間來換取時間,一般不怎麼用)
O(1):常數階;O(n):線性階;O(n2):平方階
三、線性表
線性表(List):零個或多個數據元素的有限序列。
1.順序存儲結構:一段地址連續存儲空間
數組的長度和線性表的長度區別:數組長度是存放線性表的存儲空間的長度,固定的;線性表的長度是線性表中數據元素的個數,隨插入刪除,長度改變。
存取是O(1):知道地址馬上可以取到
插入、刪除:O(n):一個個比較
注:寫代碼時要注意:程序的健壯性,插入地址適不適合,
2.鏈式存儲結構
一個節點:
數據域
指針域
鏈表的第一個節點的存儲位置叫頭指針;鏈表的最後一個節點指針爲"NULL";
注:在單鏈表的第一個節點前附設一個節點,——頭結點;
- 讀取:不知道第i個節點在哪,需要從頭開始遍歷
- 插入和刪除:
都是由兩部分組成:1.遍歷查找第i個節點;2.插入和刪除節點
3.靜態鏈表
用數組描述的鏈表(爲了不使用指針)
數組中每個元素都有兩個值,一個代表數據,一個代表遊標(相當於指針)——不一定用,但是思想比較巧、
注意遊標
4.循環鏈表
將單鏈表中的終端節點的只診斷由空指針改爲指向頭結點
- 注:循環鏈表和單鏈表的區別:在於循環的判斷條件上,原來是判斷p->next是否爲空,現在是p->next是否等於投節點(頭結點是那個沒有數據的節點)
- 將兩個循環鏈表合併,需要刪掉一個頭結點
5.雙向鏈表——用空間來換時間
一個節點包括:
數據部分;
指向前驅節點的指針;
指向後繼節點的指針。
注:在插入和刪除的時候需要改變兩個指針變量
順序:先搞定s的前驅和後繼,再搞定後節點的前驅,最後前節點的後繼
順序:順時針
free(p);
四、棧與隊列
1.棧——後進先出(Last In First Out)的線性表(LIFO結構)
存一個元素的時候,top爲0,所以空棧的時候top爲-1,用-1來判斷棧是否爲空。
棧1爲空時,top=-1;棧2爲空時,top=n;
棧1爲滿時,top=n-1;棧2爲滿時,top=0;
當在中間棧1和棧2相遇時,top1+1=top2;
棧的鏈式結構,不需要有節點,應用在遞歸上(處理器內部自身會進行的):四則運算表達式P105
2.迭代和遞歸的區別:
迭代:循環結構,不需要反覆調用函數和佔用額外的內存;
遞歸:選擇結構,使程序結構清晰簡潔,但是大量的遞歸調用會建立函數的副本,會消耗 大量的時間和內存。
3.隊列
- 隊列:數據塊、頭指針、尾指針
- 循環隊列(順序隊列):
解決出對一個數據,需要把所有數據往前移一位,浪費時間的問題,從O(n)->O(1)
當front=rear時就不能判斷是空隊列還是滿隊列,所以需要外加1.一個標示flag,flag=0,隊列爲空;flag=1,隊列爲滿。方法二:隊列滿時,仍然保留一個空位。
對第二種情況:對滿的條件是:(rear+1)%QueueSize==front——會從尾部出來,再從頭部進去。
計算隊列長度:(rear-front+QueueSizde)%QueueSize
注:在進行入隊或出對的情況下也要考慮%QueueSize
Q->rear=(Q->rear+1)%MAXSIZE;
注:在出對的情況下,就是頭結點的後繼節點出對,將頭結點的next改爲出對節點的後繼節點;
但是若鏈表除頭結點外只剩一個元素,則需要將rear指向頭節點
從a1裏面正式放數據元素。
- 循環隊列是事先申請好空間的,使用期間不釋放;而鏈隊列可以申請和釋放空間,但需要消耗一點時間。建議:在可以確定隊列長隊最大值的情況下,使用循環;無法確定,使用鏈隊列。
五、串(????匹配算法不明白)
串的存儲結構也有順序存儲和鏈式存儲,在鏈式存儲中一個節點對應一個字符,會造成很大的浪費,所以會考慮放多個字符,未被佔滿時,用非串值字符補全。但串的鏈式存儲除了在連接串與串操作時有一定的方便之外,總的來說不如順序存儲靈活,性能也不好。
1.KMP模式匹配算法
避免重複遍歷的情況,需要計算一個子串next數組:
其中MAX的計算,從頭開始,尾部對應相應的幾個,但是不包括第j位
注:字符不相等是將j=next[j];回溯
KMP算法僅當模式與主串之間存在許多“部分匹配”的情況下才體現出優勢,否則和不同的區別不大。
2.改進的KMP模式匹配算法
六、樹
- 節點擁有的子樹稱爲節點的度。度=0,是葉節點或終端節點。
樹的度是樹內各節點的度的最大值。
2.節點的層次是從根開始定義的,根爲第一層。
樹的深度或高度:樹中節點的最大層次
3.森林是m課互不相交的樹的集合。
或兄弟域
根據自己的需求可以靈活變動,看需要那麼地址。
2.孩子表示法:多重鏈表
每個節點有多個指針域,每個指針域指向一棵子樹的根節點
->
專門取一個位置來存儲節點指針域的個數,但是這時間上額損耗大。
將雙親表示法和孩子表示法綜合的:
3.孩子兄弟表示法:把一棵複雜的樹變成了一棵二叉樹
4.二叉樹:
- 二叉樹的特點:樹中某個節點只有一棵子樹,需要區分是左子樹還是右子樹(樹是不用區分的)
特殊的二叉樹:斜樹(只有左子樹或只有右子樹);滿二叉樹(每個節點都有左子樹和右子樹,完全對稱);完全二叉樹(節點的孩子可以只有一個,但是必須是連續的,一層層數)
性質3:對任何一棵二叉樹,如果其終端節點數爲n0,度爲2的節點數爲n2,則n0=n2+1。
性質5:I.如果i=1,則節點i是二叉樹的根,無雙親;如果i>1,則其雙親是節點[i/2];
II.如果2i=n,節點i有左子樹,如果2i>n,則節點沒有左子樹;
III.如果2i+1=n,節點i有右子樹,如果2i+1=n,則沒有。
鏈表:數據域,指針域,
前序遍歷:先訪問根節點;中序遍歷:先左再根節點,最後右;後序遍歷:先左再右,最後根節點;層序遍歷:一層一層訪問。
爲什麼需要這麼多形式的遍歷:因爲計算機只有循環、判斷等方式,所以需要通過遍歷方式把樹中的節點變成有意義的線性序列。
只改變打印數據的位置。
得到唯一的二叉樹:都需要中序遍歷序列,前序和後序需要一個即可。
節點有左子樹或右子樹,那麼lchild,rchild裏面存放孩子的地址;如果沒有孩子,則lchild,rchild存放的是要跳轉的地址(即前驅或後繼的地址,這兩個地址稱爲線索);通過ltag,rtag來區分是什麼地址(0,1標誌的內存空間比地址空間小,所以用他們來做標識符)
線索二叉樹就是把一個二叉樹變成了一個雙向鏈表。線索化的實質:將二叉鏈表中的空指針改爲指向前驅或後繼的線索。
這個程序不太懂??????
5.樹、森林、二叉樹的轉換
- 樹——>二叉樹:將兄弟連起來,斷開除長子外的孩子連線,兄弟的變成右子樹。
- 森林——>二叉樹:先每個樹變二叉樹;第一個二叉樹不動,後面的依次作爲前一個二叉樹的根節點的右子樹插入。
6.赫夫曼樹及應用
節點到節點的路徑,經過的連線。如果有權值,就用權值*路徑。權值路徑最小的就是赫夫曼樹。
描述:把每個點的權值從小到大排列,2個最小的放下面,和成一個值再重新選兩個最小的,重複。
N1=15;N2=30;N3=60;