二叉树
二叉树(binary tree)是一棵树,其中每个节点的儿子都不能多于两个。二叉树的一个性质是平均二叉树的深度要比N小得多,这个性质有时很重要。分析表明这个平均深度为,而对于特殊类型的二叉树,即二叉查找树(binary search tree),其深度的平均值是。不幸的是,这个深度是可以大到N-1的。
实现
因为一棵二叉树最多有两个儿子,所以我们可以用指针直接指向它们。在声明中,一个节点就是由 key(关键字)信息加上两个指向其他节点的指针(left和right)组成的结构
类型声明如下:
typedef struct TreeNode* PtrToNode;
typedef PtrToNode Tree;
struct TreeNode
{
ElementType element;
Tree left;
Tree right;
};
树一般画成圆圈并用直线连接起来,因为二叉树实际上就是图(graph)。当涉及树时,我们也不显式画出NULL指针,因为具有N个节点的每一棵二叉树都将需要N+1个NULL指针。
表达式树
表达式树的树叶是操作数(operand),比如常数或变量,而其他的节点为操作符(operator)。可以将通过递归计算左子树和右子树所得到的值应用在根处的算符操作中而算出表达式树T的值。
我们可以通过递归产生一个带括号的左表达式,然后打印出在根处的运算符,最后再递归地产生一个带括号的右表达式而得到一个(对两个括号整体进行运算的)中缀表达式(infix expression)。这种一般的方法(左,节点,右)称为中序遍历(inorder traversal);
· 另一种遍历策略是递归打印出左子树、右子树,然后打印运算符。这种遍历策略一般称为后序遍历(postorder traversal)。
第三种遍历策略是先打印出运算符,然后递归地打印出左子树和右子树。这种遍历策略称为先序遍历(preorder traversal)
构造一颗表达式树
我们现在给出一种算法来把后缀表达式转变成表达式树。由于我们已经有了将中缀表达式转变成后缀表达式的算法,因此我们能够从这两种常用类型的输入生成表达式树。
一次一个符号地读入表达式。如果符号是操作数,那么我们就建立一个单节点树并将一个指向它的指针推入栈中。如果符号是操作符,那么我们就从栈中弹出指向两棵树和的那两个指针(的先弹出)并形成一棵新的树,该树的根就是操作符,它的左、右儿子分别指向和。然后将这棵新树的指针压入栈中。
来看一个例子。设输入为:
a b + c d e + * *
前两个符号是操作数,因此创建两棵单节点树并将指向它们的指针压入栈中。
接着,读入“+”,因此弹出指向这两棵树的指针,一颗新的树形成,而将指向该树的指针压入栈中。
就像如此操作,最后得到的树如此: