学习笔记:树和二叉树

一、树的基本概念

(一)树(tree)

顾名思义,看起来像一棵倒挂的树。
它的根朝上,叶朝下。
如下图就是一颗树
在这里插入图片描述

(二)树的专业术语

结点的度:该结点子树的度称为
树的度:树中所有结点的度中的最大值
m次数树:度为m的树
分支结点:树中度不为零的结点(非终端结点)
叶子结点:为零的结点
孩子结点:每个结点的后继结点
结点层次和结点深度:从树根开始定义,根结点为第一层,其孩子结点为第二层,依次类推
树的高度和树的深度:树中结点的最大层次
森林:由n(n>0)棵互不相交的树的集合称为森林。

(三)树的性质

树中的结点数等于所有结点的的度数之和加1
度为m的树中的i层最多有 m i − 1 m ^ {i-1} mi1个结点
高度为h的m次树最多有 m h − 1 m − 1 \frac{m^h-1}{m-1} m1mh1个结点
具有n个结点的m次树的最小高度为大于等于 log ⁡ m ( n ( m − 1 ) + 1 ) \log{_m}{(n(m-1)+1)} logm(n(m1)+1)的最小整数

(四)树的遍历

先根遍历:首先访问根结点,然后遍历左子树,最后遍历右子树
后根遍历:首先遍历左子树,然后遍历右子树,最后访问根结点
层次遍历:从根结点开始按从上到下、从左到右的次序访问树中

(五)树的种类

无序树:树中任意节点的子结点之间没有顺序关系
有序树:树中任意节点的子结点之间有顺序关系
二叉树:每个节点最多含有两个子树
满二叉树:叶节点除外的所有节点均含有两个子树
完全二叉树:除最后一层外,所有层都是满节点,且最后一层缺右边连续节点的二叉树
哈夫曼树:带权路径最短的二叉树(又称为最优二叉树)

二、二叉树的基本概念

(一)二叉树(Binary tree)

二叉树是树形结构的一个重要类型
二叉树的存储结构及其算法都较为简单
二叉树的每个结点最多只能有两棵子树,且有左右之分

(二)二叉树的性质

叉树的第i层上至多有 2 i − 1 ( i ≥ 1 ) 2i-1(i≥1) 2i1(i1)个节点
深度为h的二叉树中至多含有 2 h − 1 2h-1 2h1个节点
若在任意一棵二叉树中,有 n 0 n0 n0个叶子节点,有 n 2 n2 n2个度为2的节点,则必有 n 0 = n 2 + 1 n0=n2+1 n0=n2+1
二叉树第 i i i层上至多有 2 i − 1 2^{i-1} 2i1个结点
深度为 k k k的二叉树至多有 2 k − 1 2^k-1 2k1个结点
完全二叉树按层次编号,对于任意一个编号为 i i i的结点,左孩子结点的编号为 2 i 2i 2i,右孩子结点的编号为 2 i + 1 2i+1 2i+1

(三)二叉树的遍历

前序遍历:首先访问根结点,然后遍历左子树,最后遍历右子树
中序遍历:首先访问左子树,然后遍历根节点,最后遍历右子树
后序遍历:首先遍历左子树,然后遍历右子树,最后访问根结点
层次遍历:从根结点开始按从上到下、从左到右的次序访问树

三、二叉树的基本操作

(一)存储结构

1、顺序存储结构

int Tree[MAXSIZE];//MAXSIZE根据所需结点定义,按所对应满二叉树

2、链式存储结构

struct node
{
	char data;//结点数据
	node *lchild, *rchild;//左右孩子指针
}Tree;

(二)二叉树的创建

以链式存储结构创建先序遍历二叉树为例

void Create(node *&T) //先序遍历的顺序建立二叉表
{
    char c;
    cin >> c;
    if (c == '#') //读到空结点
        T = NULL;
    else
    {
        T = new node;      //生成节点
        T->data = c;       //赋值
        Create(T->lchild); //递归创建左子树
        Create(T->rchild); //递归创建右子树
    }
}

(三)二叉树的遍历

以先序遍历为例,输出该二叉树

void Print(node *T) //先序遍历
{
    if (T) //该结点存在
    {
        cout << T->data;  //输出该结点
        Print(T->lchild); //遍历左子树
        Print(T->rchild); //遍历右子树
    }
}

四、二叉搜索树

(一)插入

void Insert(node *p, int x)
{
    if (p == NULL)
    {
        node *q = new node;
        q->l = NULL;
        q->r = NULL;
        q->data = x;
        return;
    }
    if (x < p->data)
        Insert(p->l, x);
    if (x > p->data)
        Insert(p->r, x);
    return;
}

(二)查询

node *Find(node *p, int x)
{
    if (p == NULL)
        return NULL;
    if (x == p->data)
        return p;
    if (x < p->data)
        return Find(p->l, x);
    if (x > p->data)
        return Find(p->r, x);
}

五、哈夫曼树

哈夫曼树的带权路径长度

树的带权路径长度(Weighted Path Length of Tree,简记为WPL)是从树根到树中每一结点的路径长度之和

所有二叉树中,带权路径长度最小(即代价最小)的二叉树称为最优二叉树或哈夫曼树。

代码实现

输入一个数n,然后输入n个叶结点,需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,最后输出哈夫曼树的带权路径长度(WPL)

#include <bits/stdc++.h>
using namespace std;
priority_queue<int, vector<int>, greater<int>> q;//定义升序队列,小根堆
int main()
{
    int n, x;
    cin >> n;
    for (int i = 1; i <= n; ++i)
    {
        cin >> x;
        q.push(x);//放入队列
    }
    int ans = 0, t;
    for (int i = 1; i <= n; ++i)
    {
        t = 0;
        t += q.top();
        q.pop();
        t += q.top();
        q.pop();
        ans += t;
        q.push(t);
    }
    cout << ans;
    return 0;
}

注意:
叶子上的权值均相同时,完全二叉树一定是最优二叉树,否则完全二叉树不一定是最优二叉树。
最优二叉树中,权越大的叶子离根越近。
最优二叉树的形态不唯一,WPL最小

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值