陣列、向量、鍊錶都是一種順序容器,它們提供了按位置訪問資料的手段。而非常多情況下,我們須要按資料的值來訪問元素,而不是它們的位置來訪問元素。比方有這樣乙個陣列int num[3]=,我們能夠非常高速的訪問陣列中下標為2的資料,也就是說我們知道這個資料的位置。就能夠高速訪問。有時候我們是不知道元素的位置。可是卻知道它的值是多少。如果我們有乙個變數,存放在num這個陣列中,我們知道它的值為2,卻不知道它下標是多少,也就是說不知道它的位置。
這個時候再去陣列中訪問這個元素就比較費勁,就得遍歷陣列。並且還要保證陣列中沒有反覆的元素。
二叉樹在非常大程度上攻克了這個缺點,二叉樹是按值來儲存元素。也按值來訪問元素。
怎麼做到呢,和鍊錶一樣,二叉樹也是由乙個個節點組成,不同的是鍊錶用指標將乙個個節點串接起來。形成乙個鏈。假設將這個鏈「拉直」,就像平面中的一條線。是一維的。而二叉樹由根節點開始發散,指標分別指向左右兩個子節點,像樹一樣在平面上擴散,是二維的。示意圖例如以下:
和鍊錶一樣,二叉樹也是由乙個個節點構成。顯然這乙個個節點才是二叉樹的基礎。
在鍊錶中,假設這個鍊錶是單向鍊錶。那麼每乙個節點中就須要包括乙個指向後繼節點的指標,假設是雙向鍊錶,還須要乙個指向前驅節點的指標。那麼在二叉樹的節點中。就須要包括乙個指向左子節點和乙個指向右子節點的指標。為了方便的遍歷二叉樹。還須要乙個指向父節點的指標,最後,還須要包括當前節點的值。
那麼一棵最簡單的二叉樹,示意圖是這種
那麼用乙個類來實現這個節點,如果這個二叉樹中儲存的都是int型的資料,為了方便起見。在建構函式中將所有的變數所有初始化為預設值,那麼**例如以下:
class treenode
};
然後生成這個類的三個例項,分別為node0、node1、node2。作為父節點、左子節點、右子節點。節點值初始化為10、8、14。
**例如以下
#include using namespace std;
class treenode
};int main()
輸出結果是這種
這樣我們就能夠依據輸出畫出這三個節點在記憶體中的結構圖
這樣就構成了乙個最最簡單的二叉樹。這樣假設拿到父節點。就能夠隨意的訪問它的左子節點或者右子節點,比方:
cout << (node0.left)->value << endl;
先拿到父節點。找到指向左子節點的指標,由於拿到的是乙個指標。所以就能夠用「->」訪問左子節點。上圖中有乙個比較奇怪的地方就是,node0的左子節點指標指向了node1,卻感覺指向了node1的value。由於value是類中的第乙個成員。位址會跟類的首位址重合。而處理器知道這個left指標的型別是treenode* 。所以 會從這個首位址向下讀取16位元組的內容(sizeof(treenode)=16),這樣就會讀取這個類中的全部成員。如果我們將left指標強制轉換為int* 。那麼就會向下讀取4個位元組的內容。也就是value的值。比方:
cout << *(int *)(node0.left) << endl;
輸出是8,原理是我們先拿到node的left指標。強制轉換為int* ,再用*運算子讀取當中的內容,由於型別轉換為int* 。所以處理器向下讀取4個位元組的內容,也就是8。
到如今為止,儘管構成了一棵最簡單的二叉樹,可是這樣的樹的作用不是非常大。假設想要在二叉樹中儲存大量的資料。那麼就須要定義一種結構特性。那就是左子節點的值總是小於父節點的值。右子節點的值總是大於父節點的值。
這種二叉樹叫做二叉搜尋樹,前面說到的這種結構特性。也是二叉搜尋樹的精髓所在,最開始的時候說,二叉樹是依據值來儲存元素的。那麼拿到乙個新的節點。就先比較這個節點和跟節點的大小關係,假設小於跟節點,就沿左子節點下降,否則反之。依照這種規則,直到下降到乙個空節點,也就是null。將這個節點插入到這個位置。查詢乙個元素的過程也是類似的。假設拿到乙個節點,就先跟根節點比較。假設小於跟節點。就沿左子節點查詢。否則反之。
依照這種規則。直到查詢到這個節點,或者查詢到null,代表這個節點不在這棵樹中。示意圖例如以下:
如果如今新插入乙個值為15的節點,那麼比較它和12的大小關係,比12大,沿右子節點下降。再比較和16的大小關係,比16小,沿左子節點下降。再比較和14的大小關係,比14大。沿右子節點下降。這時候到達了空節點,也就是null。
將15作為14的右子節點插入到這棵樹。查詢過程類似。
顯然這樣的結構特性不能人為的去保持。而是由**自己主動保持。與此同一時候,我們希望有乙個完整的二叉搜尋樹類。對外提供insert和erase介面,使用者僅僅管往裡面插入資料。無論內部的指標結構。
而不是像上面那樣,手動生成乙個個節點,再調整指標。那樣會累死的。
那樣旨在說明怎樣由乙個個節點構成二叉樹以及它們在記憶體中的結構。以後再學習二叉搜尋樹的實現。
樹的學習筆記 二叉樹概述
樹是乙個非常重要的非線性資料結構。簡單來說他是根據資料關係講資料元素按分支結構連線起來的。其中,a為根,b為子數,一層層擴散開來,因為非常像自然界中的大樹,所以稱為樹。在資料庫系統中,樹型結構也是資訊的重要組織形式之一。一切具有層次關係的問題都可用樹來描述。這次我介紹一下二叉樹 在電腦科學中,二叉樹...
二叉樹學習筆記
二叉樹是樹的一種特殊結構,也是一種極為重要的樹,二叉樹最重要的操作是遍歷,即按照一定的順序訪問樹中的所有節點,常見的遍歷方式有 對遍歷來說,最容易想到的方式就是遞迴,遞迴 簡單,但是效率不高,需要的棧空間比較大,非遞迴的方法 較為複雜,不過效率較高。遞迴實現 void preordervisit b...
二叉樹學習筆記
1.訪問根節點 2.在訪問第 l 層時,將 l 1 層的節點按順序儲存到佇列中 3.進入下一層並訪問該層的所有節點 4.重複上述操作直到所有層都訪問完 時間複雜度 o n 空間複雜度o n 最壞的情況下,最後一層的所有節點可能在佇列中 void levelorder node root q.dele...