二叉树中又有二叉树,也就是递归。因此使用递归创建二叉树是最简单的。思路很简单:我们申明一个结构体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; }