数据结构-二叉树

二叉树广泛应用在编译器的设计领域,以及在查找中的应用。

例如:表达式树、二叉查找树。把数据构造为二叉查找树,相当于把数据排序。排序就是为了加快查找。

树的平衡是指任何节点的深度均不得过深。极端不平衡的树相当于链表了,而链表实现插入的代价巨大。

最古老的平衡查找树:AVL树。

第i(i>=1)层上结点数最大值:2<sup>i-1</sup>,即1、2、4、8、16...。
深度为i的树的结点数最大值,或从第i(i&gt;=1)到1层所有结点数最大值:2<sup>i</sup>-1。即1、3、7、15、31。这称为满二叉树。
结点总数n=n<sub>2</sub>+n<sub>1</sub>+n<sub>0</sub>,度为0的结点数n<sub>0</sub>=n<sub>2</sub>+1。
n个结点的完全二叉树,深度=⌊log<sub>2</sub>n⌋+1。
深度k>1的完全二叉树,最少的叶子结点数=2<sup>k-2</sup>。
第i个结点的父结点编号为⌊i/2⌋,左孩子编号为2*i,右孩子编号为2*i+1。

第索引i结点的父结点编号为i时,左孩子编号为2*i + 1,右孩子编号为2*i + 2。

与普通的二叉树不同,完全二叉树可以使用数组进行隐式表示,无需使用指针。

完全二叉树的最后一个父节点的索引为 n/2-1,n为结点总数

遍历

每个结点的右子树为空的二叉树,则其先序序列和中序序列相反。

先序、中序、后序遍历是指结果要给出一个顺序表,树中的节点关系在顺序表中要满足序类型。都是要从根结点先沿左叉向下深度查找,最后根据序类型再给出结果。


算法:输出二叉树各结点的值

//中序遍历
void printtree (BiTree BT)
{
  BiTnode* p=BT;
  InitStruct(s); //构造一个数组结构s
  s.top=0;
  
  while (p || s.top!=0)
  { 
    //把p、左子、左子的左子...,存入eles。
    while (p)
    { 
      s.eles[s.top++]=p;
      p=p-&gt;lchild ;
    }
    
    if (s.top&gt;0)
    { 
      //输出eles中最后一个元素。
      p=s.eles[s.top--];
      cout &lt; &lt; p-&gt;data;//int pos=s.top,输出的元素将不在eles中继续保存。
      //遍历p的右子树
      p=p-&gt;rchild; //在下一次进入循环时,eles[pos]会被替换为p,即原p的右子结点。
    }
  }
}

<h1>树和二叉树的转换</h1>

树转二叉树:
1.将所有兄弟连接起来;
2.保留兄弟中的第一个结点与父结点的连接,断开其它的父连接;
3.结果即是使这条兄弟链变成以兄长为根的子树,子树左排列、子树内部右排列;

森林转二叉树:
1.将每棵树对应的二叉树的根作为兄弟结点连接起来;
2.同样遵循子树左排列、子树内部右排列的规则;

二叉树转森林:
把二叉树中的所有右子树中的各结点断开连接,再连接到父结点;

<h1>哈夫曼(Huffman)树</h1>
判定树:描述分类过程的二叉树。分类问题中的因素有总数N,某个类别的属性有名称、条件、占比。二叉树中分叉结点表示判断条件,叶子结点表示值。判断树中的问题在于,同一个分类问题有不同的分类算法,会产生不同的判定树。它们从表面上看有纵深形状或水平形状,那么它们的总加权遍历查找的计算量也不同。则判定树中要研究的课题是要使平均比较次数计算量最小。

哈夫曼算法和哈夫曼树:
1.给定一组类别,{p1,p2,...,pk},构造初始森林{T1,T2...Tk}
2.从森林中选两个根结点权(即占比)最小的树合并,它们分别为新树的左右子树,新树的根结点权为左右子结点权之和。
3.直到森林中只剩一棵二叉树,即哈夫曼树。
哈夫曼树中共有2n-1个结点,其中n个叶结点是初始森林中的n个结点。

哈夫曼编码:

堆是一种特殊的完全二叉树,它满足一个关键特性:堆顶是最大值或最小值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值