树的定义是递归的所以二叉树的定义也是递归的,一般先定义它的根节点在定义它的左子树再定义它的右子树,就像先序遍历一样
struct Node
{
Node(T data = T())
:_data(data)
,_lChild(NULL)
,_rChild(NULL)
{}
T _data;
Node* _lChild;
Node* _rChild;
};
void CreateBinTreePreOrder(Node<T>*& root, const T array[], const size_t size, size_t& i, const T invalue)
{
if (i < size && array[i] != invalue)
{
root = new Node<T>(array[i]);
CreateBinTreePreOrder(root->_lChild, array, size, ++i, invalue);
CreateBinTreePreOrder(root->_rChild, array, size, ++i, invalue);
}
}
二叉树的先序遍历规则先访问根节点,先按照先序遍历的规则访问左子树,之后按照先序遍历的规则访问右子树
递归算法的代码很简单但是并不是很好理解比如对下面这个二叉树的递归先序遍历
void PreOrderTraverse(const Node<T>* root)
{
if (NULL == root)
{
return;
}
cout << root->_data << " ";
PreOrderTraverse(root->_lChild);
PreOrderTraverse(root->_rChild);
}
二叉树的非递归先序遍历需要一个栈来辅助实现分三步实现
用指针p指向根节点并访问根节点将其入栈
p指向他的左子树并且档期不为空时访问它并入栈
当p为空时p指向它的右子树
void PreOrder()
{
if (_root != NULL)
{
stack<Node<T>*> s;
Node<T>* p = _root;
while (p != NULL || !s.empty())
{
while (NULL != p)
{
cout << p->_data << " ";
s.push(p);
p = p->_lChild;
}
if (!s.empty())
{
p = s.top();
p = p->_rChild;;
s.pop();
}
}
}
cout << endl;
}
中序遍历二叉树递归
void InsOrderTraverse(const Node<T>* root)
{
if (NULL == root)
{
return;
}
InsOrderTraverse(root->_lChild);
cout << root->_data << " ";
InsOrderTraverse(root->_rChild);
}
中序遍历非递归
非递归中序遍历二叉树的思想和先序遍历的方法差别不大区别在于先序遍历是在入栈是访问节点中序遍历是在出栈时访问节点
void InOrder()
{
if (_root != NULL)
{
Node<T>* p = _root;
stack<Node<T>*> s;
while (p != NULL || !s.empty())
{
while (p)
{
s.push(p);
p = p->_lChild;
}
if (!s.empty())
{
p = s.top();
cout << p->_data << " ";
p = p->_rChild;
s.pop();
}
}
cout << endl;
}
}
后序遍历二叉树
递归
void PosOrderTraverse(const Node<T>* root)
{
if (NULL == root)
{
return;
}
PosOrderTraverse(root->_lChild);
PosOrderTraverse(root->_rChild);
cout << root->_data << " ";
}
非递归后序遍历二叉树的难点在于当这个节点在第二次出现在栈顶是才访问它
非递归后序遍历二叉树有两种方法
第一种设置一个标志表示这个节点是第几次出现在栈顶如果是第二次则访问他
struct BinNode
{
BinNode(Node<T>* p)
:root(p)
,IsFirst(true)
{}
Node<T>* root;
bool IsFirst;
};
void PosOrder()
{
if (_root != NULL)
{
stack<BinNode*> s;
Node<T>* p = _root;
BinNode* tmp;
while (p != NULL || !s.empty())
{
while (NULL != p)
{
BinNode* pNewNode = new BinNode(p);
s.push(pNewNode);
p = p->_lChild;
}
if (!s.empty())
{
tmp = s.top();
s.pop();
if (tmp->IsFirst)
{
tmp->IsFirst = false;
s.push(tmp);
p = tmp->root->_rChild;
}
else
{
cout << tmp->root->_data << " ";
p = NULL;
}
}
}
}
cout << endl;
}
第二种方法是指针pCur从根节点开始一直将其左孩子一次入栈直到最左边的节点,此时如果栈顶元素没有右孩子访问该节点否则比较前一节点pPre与当前节点的右孩子的如果相等就访问该节点不相等pCur=pCur->rChild
void PosOrder1()
{
if (_root)
{
stack<Node<T>*> s;
Node<T>* pCur = _root;
Node<T>* pPre = NULL;
while (pCur || !s.empty())
{
while (pCur)
{
s.push(pCur);
pCur = pCur->_lChild;
}
pCur = s.top();
if (pCur->_rChild == NULL || pPre == pCur->_rChild)
{
cout << pCur->_data << ' ';
s.pop();
pPre = pCur;
pCur = NULL;
}
else
{
pCur = pCur->_rChild;
}
}
cout << endl;
}
}