1、创建二叉树类。二叉树的存储结构使用链表。
2、提供操作:前序遍历、中序遍历、后序遍历、层次遍历、计算二叉树结点数目、计算二叉树高度。
3、对建立好的二叉树,执行上述各操作。
4、接收键盘录入的二叉树前序序列和中序序列(各元素各不相同),输出该二叉树的后序序列。
二叉树是一种典型的非线性数据结构,它最基础的操作就是遍历,其它操作都可以视为从遍历上延伸出来的。而且,由于二叉树结构本身就是递归定义的,所以遍历方式也很容易用递归来实现,例如前序遍历可以写成:
template<class T>
void BinaryTree<T>::PreOrder(void(*Visit)(BinaryTreeNode<T>*u), BinaryTreeNode<T>* t)//前序遍历
{
if (t) {
Visit(t);
PreOrder(Visit,t->LeftChild);
PreOrder(Visit,t->RightChild);
}
}
中序和后序也是类似。层序遍历则可以使用队列来实现:
template<class T>
void BinaryTree<T>::LevelOrder(void(*Visit)(BinaryTreeNode<T>*u))
{//层序遍历二叉树
Queue<BinaryTreeNode<T>*> Q;
BinaryTreeNode<T> *t;
t = root;
while (t)
{
Visit(t);
if (t->LeftChild) Q.Add(t->LeftChild);
if (t->RightChild) Q.Add(t->RightChild);
try { Q.Delete(t); }
catch (OutofBounds) { return; }
}
}
这样就可以按层访问所有节点了。
计算节点数目也很简单,只要调用前序遍历,每次访问到一个节点就把计数变量加1,当访问完成时返回计数变量的值就是节点数目。
计算高度可以使用递归,计算左子树高度和右子树高度,当前树的高度就是左子树与右子树中较高的高度加1,当当前树为空时返回0。
通过前序与中序计算后序序列:使用树的结构,把前序序列和中序序列保存在数组中。
1.前序序列的第一个元素就是树的根节点,中序序列中该元素左边的元素就是左子树中的元素,右边的元素就是右子树中的元素。
2.通过在中序数组中顺序查找的方式找到该元素,并计算接下来要利用的前序和中序序列的首尾位置。
3.通过得到的位置再次调用方法(回到1)。将生成的左子树和右子树接在根节点上,当所有元素都被添加上后,方法结束。如果两子树都为空,不调用方法,直接用元素生成只有根节点的数。
template<class T>
BinaryTree<T>& MakeTreeByPreAndIn(T pre[], T in[], int preLeft, int preRight, int inLeft, int inRight)
{
if (preRight - preLeft == 0) {//如果两子树都为空
x.MakeTree(pre[preLeft], zero, zero);
return x;
}
int j = inLeft;
while (pre[preLeft] != in[j])
j++;
if (j == inLeft) { //如果左子树为空
BinaryTree<T> *tmp = new BinaryTree<T>;
*tmp = MakeTreeByPreAndIn(pre, in, preLeft + 1, preRight, inLeft + 1, inRight);
x.MakeTree(pre[preLeft], zero, *tmp);
delete tmp;
return x;
}
if (j + 1 > inRight) {//如果右子树为空
BinaryTree<T> *tmp = new BinaryTree<T>;
*tmp = MakeTreeByPreAndIn(pre, in, preLeft + 1, preRight, inLeft, inRight - 1);
x.MakeTree(pre[preLeft], *tmp, zero);
delete tmp;
return x;
}
//如果两子树都不为空
BinaryTree<T> *tmp1 = new BinaryTree<T>;
*tmp1 = MakeTreeByPreAndIn(pre, in, preLeft + 1, preLeft + j - inLeft, inLeft, j - 1);
BinaryTree<T> *tmp2 = new BinaryTree<T>;
*tmp2 = MakeTreeByPreAndIn(pre, in, preLeft + j - inLeft + 1, preRight, j + 1, inRight);
x.MakeTree(pre[preLeft], *tmp1, *tmp2);
delete tmp1;
delete tmp2;
return x;
}
这样就可以得到通过前序和中序序列生成的二叉树,想要得到后序序列只要通过后序遍历输出一遍就可以了。