一般來說,二叉樹使用鍊錶來定義。和普通鍊錶的區別是,由於二叉樹的每個結點有兩條出邊,因此指標變成了兩個-分別指向左子樹的根節點位址和右子樹的根節點的位址。如果某個子樹不存在,則指向null,其他地方和普通鍊錶完全相同,因此又把這種鍊錶叫做二叉鍊錶。
定義方式如下:
struct node;
由於在二叉樹中建樹前根節點不存在,因此其位址一般設為null
node *root=null;
而如果需要新建結點(例如在二叉樹中插入結點的時候),就可以使用下面的函式
node *newnode(int v)
二叉樹的常用操作有以下幾個:二叉樹的建立、二叉樹結點的查詢、修改、插入與刪除。
查詢操作是在給定資料域的條件下,在二叉樹中找到所有資料域為給定資料域的結點,並將他們的資料域修改為給定的資料域
需要使用遞迴來完成查詢與修改操作。對二叉樹進行遞迴時,遞迴式就是只對當前結點的左子樹和右子樹分別遞迴,遞迴邊界是當前結點為空時返回。例如查詢修改操作,先判斷當前結點是否是需要查詢的結點,如果是,則對其進行修改操作;如果不是,則分別往該結點的左子樹和右子樹遞迴,直到當前結點為null為止。
示例**如下:資料域以int為例:
void search(node *root,int x,int newdata)
if(root->data==x)
search(root->lchild,x,newdata);//左子樹搜尋(遞迴式)
search(root->rchild,x,newdata);//右子樹
}
由於二叉樹的形態很多,因此在題目不說明二叉樹的特點時很難給出結點的插入的具體方法,但是又必須認識到,結點的插入位置一般取決於資料域需要在二叉樹中存放的位置(這與二叉樹本身的性質有關)且對給定的結點來說,它在二叉樹的插入位置只會有乙個(否則題目本身就具有不確定性)。因此可以得到這樣的結論,即二叉樹結點的插入位置就是資料域在二叉樹中查詢失敗的位置。而由於這個位置是確定的,因此在遞迴查詢的過程中一定是只根據二叉樹的性質來選擇左子樹和右子樹中的一顆子樹進行遞迴,且最後達到遞迴邊界就是查詢失敗的地方,也就是結點需要插入的地方,由此可以得到二叉樹的插入**:
void insert(node *&root,int x)
if(由於二叉樹的性質,插入左子樹)else
}
在上述**中,很關鍵的一點是根節點指標root使用了引用&。 引用的作用就是在函式中修改root會直接修改原變數,這麼做的原因是,在insert函式中新建了結點,並把新結點的位址賦給了當層的root,如果不使用引用,root=new node這個語句對root的修改就無法作用到原變數(即上一層的root->lchild和root->rchild)上去,也就不能把結點接到二叉樹上面,因此insert函式必須加引用。
那麼為什麼前面的search函式不需要加引用呢?這是因為search函式中修改的是指標root指向的內容,而不是root本身,而對指標實現的結點內容的修改是不需要加引用的
那麼,如何判斷是否需要加引用呢?一般來說,如果函式中需要新建結點,即對二叉樹的結構作出修改,就需要加引用,如果只是修改當前結點已有的內容,或僅僅是遍歷樹,就不需要加引用。至於判斷不出來的情況,不妨直接試一下加引用和不加引用的區別
最後再提醒一句,在新建結點之後,務必令新結點的左右指標域均為null。表示這個結點暫時沒有左右子樹
二叉樹的建立其實就是二叉樹結點的插入過程,而插入所需要的結點資料域一般都會由題目中給出,因此比較常用的寫法是把需要插入的資料儲存在陣列中,然後再將它們使用insert函式乙個個插入二叉樹中,並最終返回根節點的指標root。也可以直接再建立二叉樹的過程中邊輸入資料邊插入結點。**如下:
對完全二叉樹來說,除了採用二叉鍊錶的儲存結構外,還可以有更方便的儲存方法,通過觀察可以發現,對完全二叉樹當中的任何乙個結點(設編號為x),其左孩子的編號一定是2x,而右孩子的編號一定是2x+1.也就是說,完全二叉樹可以通過建立大小為2^k的陣列來儲存所有結點的資訊,其中k為完全二叉樹的最大高度,且1號必須存放的是根節點(陣列下標從1開始,而不是0)z這樣就可以用陣列下標來表示結點的編號,且左孩子和右孩子的編號都可以直接計算到
事實上,如果不是完全二叉樹,也可以視其為完全二叉樹。即把空結點也進行實際的編號。但是會造成空間的浪費,一般很少使用。若題目中規定是完全二叉樹,那麼陣列大小只需要設為結點上限個數加1即可,這樣會大大減少編碼複雜度
除此之外,該陣列中元素存放的順序恰好為該完全二叉樹的層次遍歷序列
判斷某個結點是否為葉節點的標誌為:該結點(記下標為root)的左孩子的編號2*root大於結點的總個數n;
判斷某個結點是否為空結點的標誌為該結點的下標root大於結點總個數n。
二叉樹的儲存結構與基本操作
1 二叉樹一般使用鍊錶來儲存的,但又與一般鍊錶不同。因為二叉樹的結點有兩個出邊 左右子樹 所以鍊錶的指標域要有兩個指標分別指向結點的左右子樹的根結點的位址,把這種結構又稱為二叉鍊錶。2 定義如下 struct node node root null 3 新建乙個結點的函式 例如往二叉樹中插入新結點時...
二叉樹的儲存結構和基本操作
1 二叉樹的儲存結構 一般來說,二叉樹使用鍊錶來定義 和動態鍊錶的定義一樣。struct node 新建結點 例如往二叉樹中插入結點的時候 實現 如下 生成乙個新結點,v為結點的權值 資料域 node newnode int v 2 二叉樹結點的查詢 修改 查詢操作是指在給定資料域的條件下,在二叉樹...
樹與二叉樹的基本操作
二叉樹的鏈式儲存結構 typedef int elemtype typedef struct bitnode bitnode,bitree 統計二叉樹中度為0的結點個數 intnodedegree 0 bitree bt else return0 統計二叉樹中度為1的結點個數 intnodedegr...