二叉树的存储结构

学习反思:

二叉树学习到现在基本上告一段落了,老师的进度已经完成,剩下的就是我们自己的事情了,比如好好复习,做完剩下的练习题目。

对于我还没有做出来的那个练习题,我心中其实只有一点点想法,比如说在交换的时候变化指向左右子树的指针,但是这个过程是个递归的过程,如何把握使两个节点只交换一次,应该是需要考虑的内容之一……吧?还有就是怎么交换指针,需要交换的是这个节点的两个子节点,应该可以参考单链的操作?

总之既然能有人做出来,那么这个题就不是不能被做出来的题目。

所以……下节课这个题目应该会被完结了,正式开启图论副本,可是图论好难的亚子……连老师都说难呜呜呜,平时做的题目都是数组邻接表存储的模式,说实话用链表还真少。包括以前的一些内容,我可怜的数组都被抛弃了呜呜呜,毕竟数组只要找到逻辑规律就很容易写了,可是链表是实打实的又难思考又难写,还要写个class,真是的!

咳咳咳,学习学习。


二叉树的顺序存储:

二叉树的顺序存储结构就是用一维数组存储二叉树中的结点,并且结点的存储位置(下标)应能体现结点之间的逻辑关系——父子关系。

就是让一棵棵二叉树先变成完全二叉树的编号,然后去掉没有的节点,用数组保存存在的节点。

这个存储的条件,是利用了二叉树的父子节点的下标之间的关系:

  1. 父亲节点 的编号是子节点的两倍,所以父亲节点除以二是左孩子,除以二加一是右孩子。
  2. 完全二叉树的下标是从一开始到节点数目结束,所以开的数组大小可算,如果是只告诉你数目以及下标,完全可以依靠最大的下标来开数组(比如就开这么大)

左右子树按照这个方法找,赋值同。所以顺序存储很简单,很开心。


二叉链表

基本思想:令二叉树的每个结点对应一个链表结点,链表结点除了存放与二叉树结点有关的数据信息外,还要设置指示左右孩子的指针。

节点结构

data:数据域,存放该结点的数据信息;

lchild:左指针域,存放指向左孩子的指针;

rchild:右指针域,存放指向右孩子的指针。

代码:

template <class T>
struct BiNode
{
    T data;
    BiNode<T> *lchild, *rchild;
};

二叉链表的实现

对于一个稳稳的二叉链表,我们需要知道的除了节点的构造,最重要的就是函数怎么写。

二叉链表函数的写法十分简单,但是还是需要很多注意事项;

代码:

template <class T>
class BiTree
{    
  public:
       BiTree(); //构造函数
        void PreOrder(){PreOrder(root);} //为什么不直接写在这里面呢?因为这里需要调用根节点,然鹅根节点是私有的,我们不能调用,所以才直接让这个函数调用。
        void InOrder() {InOrder(root);} 
        void PostOrder() {PostOrder(root);} 
        void LevelOrder(){LeverOrder(root)};
  private:
        BiNode<T> *root; 
        BiNode<T> * Creat( ); 
        void PreOrder(BiNode<T> *root); 
        void InOrder(BiNode<T> *root); 
        void PostOrder(BiNode<T> *root); 
        void LevelOrder(BiNode<T> *root);
 };

剩下的那些内容,自己查书就好了,都不是很难,但是要记住关键点。

最难的是构造函数,其他的都不太需要动脑子。

构造函数:

二叉树的建立需要依靠一种名叫拓展二叉树的树,就是把所有节点的空节点都补成#的一种二叉树,对它进行前序遍历形成的序列叫做拓展前序二叉序列。

  1. 按扩展前序遍历序列输入结点的值
  2. 如果输入结点值为“#”,则建立一棵空的子树
  3. 否则,根结点申请空间,将输入值写入数据域中,
  4. 以相同方法的创建根结点的左子树
  5. 以相同的方法创建根结点的右子树

代码:

template <class T>
BiTree ::BiTree()//这是public里面的
{ 
      root=creat();
}

template <class T>
BiNode<T> * BiTree ::Creat(){//这是private里面的
     BiNode<T> *root; char ch;
    cin>>ch;
    if (ch=='# ')     root=NULL; 
    else {
        root=new BiNode<T>; 
        root->data=ch;
        root->lchild=creat(); 
        root->rchild= creat(); 
    }  
  return root
}

​​​​​​​​​​​​​​​​​​​​​非递归遍历的那些不好用,就不写了……反正我也会递归的。


求各种参数

1.求节点数目

思路:节点数目=左子树节点数目+右子树节点数目+1

*递归

边界条件:节点为空

2.求叶子数目

思路:叶子数目=左叶子+右叶子;

边界条件:叶子空返回1,自己空返回0

3.求树的深度

思路:深度=max(左子树的深度,右子树的深度)+1;

边界条件:节点为空返回0


最优二叉树——哈夫曼树

最优二叉树是所有叶子节点的权值乘路径长度相加,得到的值最小的一棵树。

哈夫曼树的特点

  1. 权值越大的叶子结点越靠近根结点,而权值越小的叶子结点越远离根结点。
  2. 只有度为0(叶子结点)和度为2(分支结点)的结点,不存在度为1的结点.

得到最优二叉树的方法是:

⑴ 初始化:由给定的n个权值{w1,w2,…,wn}构造n棵只有一个根结点的二叉树,从而得到一个二叉树集合F={T1,T2,…,Tn};

⑵ 选取与合并:在F中选取根结点的权值最小的两棵二叉树分别作为左、右子树构造一棵新的二叉树,这棵新二叉树的根结点的权值为其左、右子树根结点的权值之和;

⑶ 删除与加入:在F中删除作为左、右子树的两棵二叉树,并将新建立的二叉树加入到F中;

 ⑷ 重复⑵、⑶两步,当集合F中只剩下一棵二叉树时,这棵二叉树便是哈夫曼树。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值