树
基本概念:树是 结点的有限集
- 有且仅有一个特定的称为根的结点
- 当 时,其余结点可分为m个互不相交的有限集,每个集合都是一棵树,是根的子树。
其他概念:
- 结点的度:子树的个数;
- 树的度:树的节点中最大度
- 叶节点(终端结点):度为0的节点;而分支结点是度不为0的结点。
- 树的深度:树所有结点中最大层次(根节点的层次为1)
- 路径长度:结点个数-1,或者说是分支条数
- 兄弟结点是父结点相同的结点
- 森林是 棵互不相交的树的集合
二叉树
二叉树是另一种树形结构,每个结点至多只有两棵子树,且有左右之分,需要注意的是,从树的概念衍生来的二叉树是可以为空树的。
性质
- 在二叉树的第 层上至多有 个结点(i>=1)
- 深度为 的二叉树至多有 个结点(k>=1),由此,深度为 且有 个结点的二叉树是满二叉树;而完全二叉树是其 个结点与满二叉树的 个结点编号一致。
- 对任何一棵二叉树T,若叶结点数为 ,度为2的结点数为 ,则 。
- 对于完全二叉树T,具有n个结点,其深度为
- 对于有 个结点的完全二叉树,i为结点编号,如果 则 是二叉树的根,若 则其双亲是 (向下取整);另外,如果 则 无左孩子, 则 无右孩子
存储结构
- 顺序存储,以数组下标表示结点编号,明显可以看出,如果树不为完全二叉树,则浪费了很多存储空间
- 链式存储 分为数据域和左右指针域,链的头指针指向根节点,还有一种三叉链表,多加了一个指向双亲结点的指针。
二叉树的遍历和线索二叉树
遍历
- 前序遍历 根结点-左子结点-右子结点
- 中序遍历 左子结点-根结点-右子结点
- 后序遍历 左子结点-右子结点-根结点
三种遍历方式正好对应波兰式,中缀表达式和逆波兰式
bool PreOrderTraverse(BinTree T)
{
if (!T)
return 1;
else
{
Visit(T->data);
PreOrderTraverse(T->left);
PreOrderTraverse(T->right);
}
return 1;
}
遍历算法的不同之处仅仅为访问结点的先后关系,其实递归执行过程是完全一样的,仿照递归执行状态中递归栈的变化可写出相应的非递归算法,若栈顶记录的指针非空,则遍历左子树将左指针入栈;若栈顶记录的指针为空,说明应当返回上一层,若从右子树返回,不必保存当前的根指针,直接修改指针即可。
bool InOrderTraverse(BinTree T)
{
InitStack(s);
BinTree p=T;
while(p||!isempty(s))
{
if(p)
{
Push(s,p);
p=p->left;
}
else
{
Pop(s,p);
if(!Visit(p->data))
return 0;
p=p->r;
}
}
return 1;
}