二叉樹的定義是一棵樹的每一個節點最多隻有兩個兒子,使二叉樹成爲二叉查找樹的性質是,對於樹中的每一個節點X,它的左子樹中的關鍵字比X中的小,而它的右子樹則比X中的關鍵字大。算法
二叉樹節點能夠定義成以下形式:spa
1 struct BSTreeNode { 2 BSTreeNode* pLeft; 3 BSTreeNode* pRight; 4 int nData; 5 };
二叉樹很是簡單,下面再介紹幾個基本的操做。指針
1、插入code
插入一個關鍵字Key從根節點開始,若是Key比此節點關鍵字大,則往右邊繼續往下,直到節點爲空,如下代碼爲非遞歸寫法,要寫成遞歸寫法也是很是容易的blog
1 //返回樹的根節點 2 BSTreeNode* BSTreeInsert(BSTreeNode* pRoot, int nData) { 3 if (pRoot == nullptr) { 4 pRoot = new BSTreeNode; 5 pRoot->pLeft = pRoot->pRight = nullptr; 6 pRoot->nData = nData; 7 } 8 else { 9 BSTreeNode* pParent = pRoot; 10 BSTreeNode* pCursor = pParent; 11 while (pCursor) { 12 pParent = pCursor; 13 if (nData > pCursor->nData) 14 pCursor = pCursor->pRight; 15 else if (nData < pCursor->nData) 16 pCursor = pCursor->pLeft; 17 else 18 return pRoot; 19 } 20 pCursor = new BSTreeNode; 21 pCursor->nData = nData; 22 pCursor->pLeft = pCursor->pRight = nullptr; 23 if (nData > pParent->nData) 24 pParent->pRight = pCursor; 25 else if (nData < pParent->nData) 26 pParent->pLeft = pCursor; 27 } 28 return pRoot; 29 }
2、獲取最小值排序
一直往左邊遍歷,直到節點爲空。遞歸
1 BSTreeNode* BSTreeMinimumNode(BSTreeNode* pRoot) { 2 if (pRoot == nullptr) 3 return nullptr; 4 5 BSTreeNode* pCursor = pRoot; 6 while (pCursor->pLeft) { 7 pCursor = pCursor->pLeft; 8 } 9 return pCursor; 10 }
3、獲取最大值class
一直往右邊遍歷,直到節點爲空。二叉樹
1 BSTreeNode* BSTreeMaximumNode(BSTreeNode* pRoot) { 2 if (pRoot == nullptr) 3 return nullptr; 4 5 BSTreeNode* pCursor = pRoot; 6 while (pCursor->pRight) { 7 pCursor = pCursor->pRight; 8 } 9 return pCursor; 10 }
4、刪除遍歷
二叉查找樹的刪除稍複雜一些,先查找此樹待刪除節點,當找到此節點(設爲X)時,先判斷左子節點和右子節點是否爲空,若是有任一子節點爲空,則刪除很是容易,只須要將空節點的兄弟節點代替要刪除的節點 便可。而若是左子節點和右子節點都不爲空,則在待刪除節點的右子樹中找一個值最小的節點(設爲Y),而後將此最小節點的值賦值給待刪除結點X,而後在右子樹中刪除此最小節點Y,並且Y一定左子節點爲空的,刪除會很是簡單。代碼以下:
1 BSTreeNode* BSTreeDelete(BSTreeNode* pRoot, int nData) { 2 if (pRoot == nullptr) 3 return nullptr; 4 else if (nData > pRoot->nData) { 5 pRoot->pRight = BSTreeDelete(pRoot->pRight, nData); 6 return pRoot; 7 } 8 else if (nData < pRoot->nData) { 9 pRoot->pLeft = BSTreeDelete(pRoot->pLeft, nData); 10 return pRoot; 11 } 12 else { 13 if (pRoot->pLeft == nullptr || pRoot->pRight == nullptr) { 14 BSTreeNode* pNode = (pRoot->pRight == nullptr) ? pRoot->pLeft : pRoot->pRight; 15 delete pRoot; 16 return pNode; 17 } 18 else { 19 BSTreeNode* pNode = BSTreeMinimumNode(pRoot->pRight); 20 pRoot->nData = pNode->nData; 21 pRoot->pRight = BSTreeDelete(pRoot->pRight, pNode->nData); 22 return pRoot; 23 } 24 } 25 }
返回值是傳入的樹被刪除nData後樹的根節點。刪除後,經過遞歸回溯,將返回值賦值給原節點對應的左子樹或右子樹。
在《算法導論》裏面,採用的是非遞歸刪除,因此在那裏討論若是X的左右子節點不爲空,則查找右子樹中的後繼節點Y(也就是最小節點)時,還討論了若是後繼Y是X的右子節點的狀況,若是是右子節點則直接拿Y替換X,不然拿Y的右子節點先替換X中的值,再拿Y的右子節點替換Y。我的感受不如遞歸刪除的代碼簡潔明瞭。並且非遞歸刪除裏面,節點必須保持對父節點的引用,也就是說節點的定義裏面要加一個父節點指針。
5、二叉樹的遍歷
二叉樹的遍歷有三種遍歷方式,先序遍歷,中序遍歷,後序遍歷
先序遍歷:自己,左子節點,右子節點。
中序遍歷:左子節點,自己,右子節點。
後序遍歷:左子節點,右子節點,自己。
以如下二叉樹爲例:
先序遍歷輸出:ABDECFG
中序遍歷輸出:DBEAFCG
後序遍歷輸出:DEBFGCA
由以上可知,中序遍歷輸出的是排序好的結果。
6、查找
查找就不用說了,二叉查找樹,在平均狀況下,時間爲O(logN),也就是樹的高度