[计算机软件及应用]6 树
第六章 树和二叉树 Zhang yuxiang cauc ? 引言 树是一类重要的非线性结构; 树讨论层次和分支关系。 目 录 6.1 树的有关概念 6.2 二叉树 6.2.1 定义 6.2.2 性质 6.2.3 存储结构 6.3 遍历二叉树和线索二叉树 6.3.1 遍历二叉树 6.3.2 线索二叉树 6.4 树和森林 6.4.1 树的存储结构 6.4.2 森林和二叉树的转换 6.5 哈夫曼树及应用 6.1 树的定义 定义 定义:树(tree)是n(n>0)个结点的有限集T,其中: 有且仅有一个特定的结点,称为树的根(root) 当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,……Tm,其中每一个集合本身又是一棵树,称为根的子树(subtree) 特点: 树中至少有一个结点——根 树中各子树是互不相交的集合 基本术语 结点(node)——表示树中的元素,包括数据项及若干指向其子树的分支 结点的度(degree)——结点拥有的子树数 叶子(leaf)——度为0的结点 孩子(child)——结点子树的根称为该结点的孩子 双亲(parents)——孩子结点的上层结点叫该结点的~ 兄弟(sibling)——同一双亲的孩子 树的度——一棵树中最大的结点度数 结点的层次(level)——从根结点算起,根为第一层,它的孩子为第二层…… 深度(depth)——树中结点的最大层次数 森林(forest)——m(m?0)棵互不相交的树的集合 6.2 二叉树 定义 定义:二叉树是n(n?0)个结点的有限集,它或为空树(n=0),或由一个根结点和两棵分别称为左子树和右子树的互不相交的二叉树构成 特点 每个结点至多有二棵子树(即不存在度大于2的结点) 二叉树的子树有左、右之分,且其次序不能任意颠倒 基本形态 性质1: 满二叉树 定义: 特点:每一层上的结点数都是最大结点数。 性质5: 如果对一棵有n 个结点的完全二叉树的结点按层序编号,则对任一结点i(1?i?n),有: (1) 如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是?i/2? (2) 如果2i>n,则结点i无左孩子;如果2i?n,则其左孩子是2i (3) 如果2i+1>n,则结点i无右孩子;如果2i+1?n,则其右孩子是2i+1 顺序存储结构 实现:按满二叉树的结点层次编号,依次存放二叉树中的数据元素 特点: 结点间关系蕴含在其存储位置中 浪费空间,适于存满二叉树和完全二叉树 链式存储结构 二叉链表 将广义表二叉树转为二叉链表 (A(B(C), D(E(, G), F))) 二叉链表见右图 算法: (1) 定义指针b(指向二叉链表); (2) 读入一个字符ch; (3) switch(ch){ 若为“(”,空指针p进栈,k=1,break; 若为“)”,出栈,break; 若为“,”,k=2,break; 若为“字母”,生成结点p,将p链入b中;} (4) 执行(2),直到ch为空(ch==‘\0’)。 default: p=(BTree *)malloc(sizeof(BTree)); p->data=ch;p->left=p->right=NULL; if (b==NULL) b=p; //根结点 else{ switch(k) { case 1:stack[top]->left=p;break; case 2:stack[top]->right=p;break; } } } j++; ch=str[j]; } } void main() { BTree *b; char s[40]={"(a(b(c),d(e(,f),g)))"}; creatree(b, s); } 一、二叉树的遍历 先序遍历:先访问根结点,然后分别先序遍历左子树、右子树 中序遍历:先中序遍历左子树,然后访问根结点,最后中序遍历右子树 后序遍历:先后序遍历左、右子树,然后访问根结点 按层次遍历:从上到下、从左到右访问各结点 递归算法 方法一:结点全部进栈,逐个退栈 (1) 当前指针指向根结点; (2) 打印当前结点并进栈,当前指针指向其左孩子,重复(2),直到左孩子为NULL; (3) 依次退栈,将当前指针指向右孩子; (4) 若栈非空或当前指针非NULL,执行(2);否则结束。 方法二: 右子结点、左子结点进栈,左子结点退栈 (1) 根结点进栈; (2) 若栈非空,退栈并访问该结点; (3) 若右孩子不空,则入栈; (4) 若左孩子