写一个算法统计二元树 t 中度为 2 结点的数目_数据与算法总结——基本数据结构2(树)...

本文介绍了二叉树的基本概念,包括结点、度、二叉树的性质、遍历方法以及Huffman树和Huffman编码。重点讨论了如何统计二叉树中度为2的结点数量,并提供了相关算法的理解和实现。
摘要由CSDN通过智能技术生成

81ba085b4519afaeb47e96e110520e7d.png

2 基本数据结构

2.5 树

2.5.1 基本概念

首先是一些基本概念:结点、结点的度、分支结点、叶子结点、树的度、k叉树、结点的层次、树的深度。

然后是一些基于小学奥数的性质:

性质一:树中的结点数目等于所有结点的度数和加1。

性质二:若k叉树的层次从1开始,度为k的树中第i层上至多

equation?tex=k%5E%7Bi-1%7D 个结点
equation?tex=%28i%E2%89%A51%29

性质三:深度为h的k叉树至多有

equation?tex=%5Cfrac%7Bk%5Eh-1%7D%7Bk-1%7D 个结点。

性质四:具有n个结点的k叉树最小深度为

equation?tex=%5Clceil+log_k%28n%5Ctimes+%28k-1%29%2B1%29+%5Crceil

2.5.2 二叉树

然后是二叉树以及基于小学奥数的二叉树的性质:

性质一:对任何一棵二叉树,如果其叶子结点个数为

equation?tex=n_0
equation?tex=n_2 个度为2的结点,则有
equation?tex=n_0%3Dn_2%2B1

性质二:若二叉树的层次从1开始,则在二叉树的第i层最多有

equation?tex=2%5E%7Bi-1%7D 个结点
equation?tex=%28i%E2%89%A51%29

性质三:深度为h的二叉树最多有

equation?tex=2%5Eh-1 个结点
equation?tex=%28h%E2%89%A51%29

性质四:具有n个结点的完全二叉树的深度为

equation?tex=%5Clceil+log_2%28n%2B1%29+%5Crceil

2.5.3 二叉树的表示

顺序表示:用顺序表来存储和表示二叉树,按照从上到下从左到右的顺序写完全二叉树,如果有空的地方,在顺序表里也空出来。

链式表示:结点由数据域data+两个指针域lchild和rchild

typedef struct tnode
{
    ElemType data;
    struct tnode *lchild;
    struct tnode *rchild;
}TreeNode;

2.5.4 二叉树的遍历

设访问根结点极为V,遍历根的左子树记为L,右R。

先序遍历:V-L-R

中序遍历:L-V-R

后序遍历:L-R-V

对于一棵二叉树1-2-3-4-5-6

5505075cffb482e5dedfb2a1bee5db7a.png
一棵二叉树

先序遍历:0-1-3-4-2-5-6

中序遍历:3-1-4-0-5-2-6

后序遍历:3-4-1-5-6-2-0

这是用的递归的思想做的遍历,代码如下:

//先序遍历
void BinaryTree::PreOrder(
    TNODE *t;
    void(*Visit)(TNODE*))
{
    if(t)
    {
        Visit(t);
        PreOrder(t->lChild, Visit);
        PreOrder(t->rChild, Visit);
    }
}

//中序遍历
void BinaryTree::InOrder(
    TNODE *t;
    void(*Visit)(TNODE*))
{
    if(t)
    {
        InOrder(t->lChild, Visit);
        Visit(t);
        InOrder(t->rChild, Visit);
    }
}

//后序遍历
void BinaryTree::PostOrder(
    TNODE *t;
    void(*Visit)(TNODE*))
{
    if(t)
    {
        PostOrder(t->lChild, Visit);
        PostOrder(t->rChild, Visit);
        Visit(t);
    }
}

非递归算法利用栈来实现

还是这个图

5505075cffb482e5dedfb2a1bee5db7a.png

先序遍历:

访问0,2入栈,指向1;访问1,4入栈,指向3;访问3,叶子结点,4出栈,指向4;访问4,叶子结点,2出栈,指向2;访问2,6入栈,指向5;访问5,叶子结点,6出栈,指向6;访问6,栈空,结束。

中序遍历:

0入栈,1入栈,3入栈,叶子结点,访问3,访问1,4入栈,访问4,访问0,2入栈,5入栈,访问5,访问2,6入栈,访问6。

后序遍历:

0a入栈,1a入栈,3a入栈,置为3b,访问3,置为1b,4a入栈,置为4b,访问4,访问1,置为0b,2a入栈,5a入栈,置为5b,访问5,置为2b,6a入栈,置为6b,访问6,访问2,访问0,结束。

层序遍历:

用队列实现:0入队,0出队;1入队,2入队;1出队,3入队,4入队;2出队,5入队,6入队;3出队,4出队,5出队,6出队,完成。

2.5.5 Huffman树与Huffman编码

对于Huffman Tree,先说它的一些概念:

结点到结点的分支称为路径。路径上的分支数称为路径长度,记为l。结点的路径长度定义为从根结点到该结点的路径上分支的数目。树的路径长度是从树根到所有叶子结点的路径长度之和。 树的带权路径长度为树中所有叶子结点的带权路径长度之和,记为WPL

在所有路径长度相同的二叉树中,WPL最小的树称为最优二叉树(Huffman Tree)。

Huffman Tree的构造:构造目标是根据n个给定的权值

equation?tex=%5C%7Bw_1%2Cw_2%2C%5Ccdots%2Cw_n%5C%7D ,构造一棵二叉树,二叉树的n个叶子结点的权值分别为
equation?tex=w_1%2Cw_2%2C%5Ccdots%2C+w_n 。树中只有度为0和2的点(正则)。

构造过程:

构造n棵二叉树的集合
equation?tex=F%3D%5C%7BT_1%2CT_2%2C%5Ccdots%2C+T_n%5C%7D ,其中每棵二叉树中均只含一个带权值为
equation?tex=w_i 的根结点。在F中选最小权值的两棵树,分别作为左、右子树构造新的,新树根结点权值为这两个之和,重复,直到F中只含一棵树。

下面是一个例子:

9cec4391f7ae606e088dc3c7ecdcde56.png

b5863c953977d2adf2ec41f088eb7cec.png

19c82e3e02681d2d05dcd2c2b31ce565.png

7d14eb5138c90a2df9ca91935221438a.png

然后来看编码问题:

定长编码就没什么好说的了,0和1排列组合,重点是变长编码,这个就涉及到优化问题了。概率大的给短码,概率小的给长码。一种就是前缀编码,可以用二叉树来表示。

定长编码:

93a31eabc9fc3bdcda7236d853045883.png

前缀编码:

3801fc397a53a4ecdd054dad8c90c537.png

最后登场的就是Huffman编码:

equation?tex=%5Cbegin%7Baligned%7D+S%26%3D%5C%7Ba%280.12%29%2Cb%280.40%29%2Cc%280.15%29%2Cd%280.08%29%2Ce%280.25%29%5C%7D%5C%5C+%5Crightarrow+S%26%3D%5C%7Bb%280.40%29%2Cc%280.15%29%2Ce%280.25%29%2C+%5C%7Bd%2Ca%5C%7D%280.20%29%5C%7D%5C%5C+%5Crightarrow+S%26%3D%5C%7Bb%280.40%29%2Ce%280.25%29%2C%5C%7Bc%2Cd%2Ca%5C%7D%280.35%29%5C%7D%5C%5C+%5Crightarrow+S%26%3D%5C%7Bb%280.40%29%2C%5C%7Be%2Cc%2Cd%2Ca%5C%7D%280.60%29%5C%7D%5C%5C+%5Crightarrow+S%26%3D%5C%7B%5C%7Bb%2Ce%2Cc%2Cd%2Ca%5C%7D%281.00%29%5C%7D+%5Cend%7Baligned%7D

示意图:

00bc2b320dacd90968edd1fe8cfed29e.png

编码:

equation?tex=a%5Cqquad+%5Cqquad+1111%5C%5C+b%5Cqquad+%5Cqquad+%5Cquad+%5C+%5C++0%5C%5C+c%5Cqquad+%5Cqquad+%5C+%5C++110%5C%5C+d%5Cqquad+%5Cqquad+1110%5C%5C+e%5Cqquad+%5Cqquad+%5Cquad++10

除了单向的,还可以有双向的Huffman编码

8cbb7b93696936bdc27987254fc05011.png

Huffman编码的不足:没有错误保护功能,需要精确统计文本的字符出现概率,编码速度较慢。

2.5.6 二叉搜索树(BST)

空树或者有以下特点:

每个结点都有一个关键字并且:任意结点关键字大于等于该结点左子树中所有结点含有的关键字;同时该结点的关键字小于等于右子树中所有结点含有的关键字。

搜索就很简单啦,比较看谁大谁小然后顺着路就过去了。

插入类似于查找,在查找失败之后执行插入操作就ok了。

举个例子:A S E R C H I N,构造一棵BST

f09d65c5264d0d7d8b9f2dddab3cd0dd.png

由二叉树的前序序列和中序序列可以唯一地确定一棵二叉树。

举个例子:

前序序列为:0-1-2-3-4-5-6-7-8;中序序列为:2-1-4-3-0-5-7-6-8

得到的二叉树为:

e3bd11a3cdce67c9eb4e2129b77aa32e.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值