二叉樹中又有二叉樹,也就是遞歸。因此使用遞歸創建二叉樹是最簡單的。思路很簡單:我們申明一個結構體TREENODE,該結構體有三個成員,分別是Value,LeftChild和RightChild。
代碼如下:
typedef struct _struct_tree_node { char m_cData; _struct_tree_node* m_pLeftChild; _struct_tree_node* m_pRightChild; }TREENODE, *LPTREENODE;
首先我們new一個TREENODE,將輸入一個值賦給Value,LeftChild=調用自身,RightChild=調用自身。完事以后返回。
代碼如下:
LPTREENODE RecursionCreateTree(char* pValue) { if(!pValue || !(*pValue) || *pValue == '#')return NULL; static int nIndex = 0; LPTREENODE pTemp = new TREENODE; memset(pTemp, 0, sizeof(TREENODE)); pTemp->m_cData = *(pValue + nIndex++); pTemp->m_pLeftChild = RecursionCreateTree(pValue); pTemp->m_pRightChild = RecursionCreateTree(pValue); return pTemp; }
遞歸創建是不是很簡單?哈哈。。。別高興得太早,這個函數是一次性的喔,也就是說只能創建一顆二叉樹,不能創建第二顆。原因就出在了nIndex這個靜態變量這里。如果你需要再創建一顆二叉樹,那么再創建之前需要將nIndex賦為0。
如果換做非遞歸的方式創建,就沒有這個問題了。但是非遞歸創建稍微復雜一點點,需要用到棧stack。
原理很簡單:
0、判斷Value是否等於‘#’,如果是:執行第5步;否則:執行第1步
1、創建節點
2、判斷棧是否為空,如果為空:執行第4步;否則:執行第3步
3、判斷方向是否為Left,如果是:棧頂元素的左孩子等於第1步創建的節點,執行第4步;否則:棧頂元素的右孩子等於第1步創建的節點,刪除棧頂元素,方向改為左,執行第4步。
4、節點入棧
5、判斷方向是否等於右,如果是:刪除棧頂元素;如果不是:將方向改為右
具體代碼如下:
// 先序創建 TEMPTYPE bool CBinaryTree<type>::FirstOrderCreate(__in const type* pValue, __in UINT nSize) { if (!pValue || !nSize)return false; const type* pTempValue = pValue; stack<LPTREENODE>* pStack = new stack<LPTREENODE>; bool IsDirection = true;// true:左 false:右 // 創建子節點 while (*pTempValue) { while (*pTempValue != m_Make/*m_Make等於‘#’號*/){ // 創建子節點 auto p = new TREENODE; memset(p, 0, sizeof(TREENODE)); p->m_Data = *pTempValue; // 掛在左/右節點 if (!pStack->empty()){ if (IsDirection){// 棧頂左節點 pStack->top()->m_pLeftChild = p; } else{// 棧頂右節點,子樹創建完成,刪除棧頂元素,方向變為左,既創建左節點 pStack->top()->m_pRightChild = p; pStack->pop(); IsDirection = true; } // 節點入棧 pStack->push(p); } else {// 棧空,既跟節點 m_pTree = p; pStack->push(p); } pTempValue++; } pTempValue++; // 如果方向為右,刪除棧頂元素;否則方向變為右 if (!IsDirection){ pStack->pop();} else IsDirection = false; } delete pStack; return true; }