树和二叉树

一、树

1.概述

树(Tree)是n(n≥0)个结点的有限集合,当n=0时,为空树;n>0时,为非空树。任意一棵非空树,满足:
1)有且仅有一个称之为根的结点;
2)除根结点以外的其余结点可分为m(m>0)个互不相交的有限集T1, T2, …, Tm, 其中每一个集合本身又是一棵树,并且称为根的子树(SubTree)。
在这里插入图片描述

2.树的相关术语

● 节点——节点包含数据元素及若干指向子树的分支信息。
● 节点的度——节点拥有的子树个数。
● 树的度——树中节点的最大度数。
● 终端节点——度为0的节点,又称为叶子
● 分支节点——度大于0的节点。除了叶子都是分支节点。
● 内部节点——除了树根和叶子都是内部节点。
● 节点的层次——从根到该节点的层数(根节点为第1层)。
● 树的深度(或高度)——指所有节点中最大的层数。
● 路径——树中两个节点之间所经过的节点序列。
● 路径长度——两节点之间路径上经过的边数。
● 双亲、孩子——节点的子树的根称为该节点的孩子,反之,该节点为其孩子的双亲。
● 兄弟——双亲相同的节点互称兄弟。
● 堂兄弟——双亲是兄弟的节点互称堂兄弟。
● 祖先——从该节点到树根经过的所有节点称为该节点的祖先。
● 子孙——节点的子树中的所有节点都称为该节点的子孙。
● 森林——由m(m≥0)棵不相交的树组成的集合。

3.树的存储结构
顺序存储

分为双亲表示法、孩子表示法和双亲孩子表示法。
在这里插入图片描述
3种表示法的优缺点如下。
双亲表示法只记录了每个节点的双亲,无法直接得到该节点的孩子;孩子表示法可以得到该节点的孩子,但是无法直接得到该节点的双亲,而且由于不知道每个节点到底有多少个孩子,因此只能按照树的度(树中节点的最大度)分配孩子空间,这样做可能会浪费很多空间。双亲孩子表示法是在孩子表示法的基础上,增加了一个双亲域,可以快速得到节点的双亲和孩子,其缺点和孩子表示法一样,可能浪费很多空间。

链式存储

(1)孩子链表表示法
类似于邻接表,表头包含数据元素并指向第一个孩子指针,将所有孩子放入一个单链表中。在表头中,data存储数据元素,first为指向第1个孩子的指针。单链表中的节点记录该节点的下标和下一个节点的地址。仍以图6-10为例,其孩子链表表示法如图6-12所示。
在这里插入图片描述

(2)孩子兄弟表示法
节点除了存储数据元素之外,还有两个指针域lchild和rchild,被称为二叉链表。lchild存储第一个孩子地址,rchild存储右兄弟地址。其节点的数据结构如图6-13所示。
在这里插入图片描述
树如图所示:
在这里插入图片描述

4.树、森林与二叉树的转换
(1).树和二叉树的转换

秘诀:长子当作左孩子,兄弟关系向右
在这里插入图片描述
还原时逆操作即可.

(2).森林和二叉树的转换

可以把森林中的每棵树的树根看作兄弟关系,因此3棵树的树根B、C和D是兄弟,兄弟关系在右斜线上,其他的转换和树转二叉树一样,长子当作左孩子,兄弟关系向右斜。或者把森林中的每一棵树转换成二叉树,然后把每棵树的根节点连接在右斜线上即可
在这里插入图片描述
以上大部分内容来自陈小玉老师的《趣学数据结构》

二、二叉树

1.概述

二叉树(binary tree)是n(n≥0)个节点构成的集合,
它或为空树(n=0),或满足以下两个条件:
1)有且仅有一个称为根的节点;
2)除根节点以外,其余节点分为两个互不相交的子集T1和T2,分别称为T的左子树和右子树,且T1和T2本身都是二叉树。

二叉树是一种特殊的树,它最多有两个子树,分别为左子树和右子树,二者是有序的,不可以互换。也就是说,二叉树中不存在度大于2的节点。

两种特殊的二叉树:
●满二叉树:一棵深度为k且有2k-1个节点的二叉树。满二叉树每一层都“充满”了节点,达到最大节点数,如图6-24所示。
●完全二叉树:除了最后一层外,每一层都是满的(达到最大节点数),最后一层节点是从左向右出现的

2.性质

性质1:在二叉树的第i层上至多有 2(i-1) 个节点。
性质2:深度为k的二叉树至多有 2^k-1个节点。
性质3:对于任何一棵二叉树,若叶子数为n0,度为2的节点数为n2,则n0=n2+1。
性质4:具有n个节点的完全二叉树的深度必为 log2n+1。
性质5:对于完全二叉树,若从上至下、从左至右编号,则编号为i的节点,其左孩子编号必为2i,其右孩子编号必为2i +1,其双亲的编号必为i/2。

3. 二叉树的存储结构

1.顺序存储(可以使用树存储的三种方法,也可使用两个数组,一个记录左孩子,一个记录右孩子,节点和索引相对应)
2. 链式存储:二叉链表(最常用的那个,一个存放数据,还有两个指针),三叉链表

4.二叉树的创建
1.询问法
void createtree(Btree &T){
	char check;
	T = new Bnode;
	cout<<"请输入节点信息:"<<endl;
	cin>>T->data;
	cout<<"是否添加"<<T->data<<"的左孩子? (Y/N)"<<endl;//询问是否创建T的左子树
	cin>>check;
	if(check=='Y'){
		createtree(T->lchild); 
	} else{
		T->lchild = NULL;
	} 
	cout<<"是否添加"<<T->data<<"的右孩子? (Y/N)"<<endl;//询问是否创建T的左子树
	cin>>check;
	if(check=='Y'){
		createtree(T->rchild); 
	} else{
		T->rchild = NULL;
	} 
} 
2.补空法(更常用)
void Createtree(Btree &T) {	/*创建二叉树函数*/
	char ch;
	cin>>ch;
	if(ch=='#'){
		T = NULL;
	} else{
		T = new Bnode;
		T->data = ch;
		Createtree(T->lchild);
		Createtree(T->rchild);
	}
}

三、二叉树的遍历

直接上代码

#include<iostream>
#include<queue>
using namespace std;
typedef struct Bnode {
	char data;
	Bnode *lchild,*rchild; 
} Bnode,*Btree;//Btree指代二叉树 

void Createtree(Btree &T) {	/*创建二叉树函数*/
	char ch;
	cin>>ch;
	if(ch=='#'){
		T = NULL;
	} else{
		T = new Bnode;
		T->data = ch;
		Createtree(T->lchild);
		Createtree(T->rchild);
	}
}

void preorder(Btree T){//先序遍历 
	if(T){
		cout<<T->data<<" ";
		preorder(T->lchild);
		preorder(T->rchild);
	}
}

void inorder(Btree T){//中序遍历 
	if(T){
		preorder(T->lchild);
		cout<<T->data<<" ";
		preorder(T->rchild);
	}
} 

void posorder(Btree T){//后序遍历 
	if(T){
		posorder(T->lchild);
		preorder(T->rchild);
		cout<<T->data<<" ";
	} 
} 

bool Leveltraverse(Btree T){
	Btree p;
	if(!T){//如果是空树则结束 
		return false;
	}
	queue<Btree> Q;
	Q.push(T);
	while(!Q.empty()){
		p=Q.front();
		Q.pop();
		cout<<p->data<<" ";
		if(p->lchild){
			Q.push(p->lchild);
		}
		if(p->rchild){
			Q.push(p->rchild);
		}
	}
	return true;
}

int main() {
	Btree mytree;
	cout<<"按先序次序输入二叉树中结点的值(孩子为空时输入#),创建一棵二叉树"<<endl;
	Createtree(mytree);//创建二叉树
	cout<<endl;
	cout<<"二叉树的先序遍历结果:"<<endl;
	preorder(mytree);//先序遍历二叉树
	cout<<endl;
	cout<<"二叉树的中序遍历结果:"<<endl;
	inorder(mytree);//中序遍历二叉树
	cout<<endl;
	cout<<"二叉树的后序遍历结果:"<<endl;
	posorder(mytree);//后序遍历二叉树
	cout<<endl;
	cout<<"二叉树的层次遍历结果:"<<endl;
	Leveltraverse(mytree);//层次遍历二叉树
	return 0;
}
运行结果:

在这里插入图片描述
测试的二叉树:
在这里插入图片描述

四、树的应用

1.前序/后序和中序还原建立二叉树.
#include <iostream>
using namespace std;
typedef struct node
{
    char data;
    struct node *lchild,*rchild;
}BiTNode,*BiTree;

BiTree pre_mid_createBiTree(char *pre,char *mid,int len) //前序中序还原建立二叉树
{
    if(len==0)
        return NULL;
    char ch=pre[0];  //找到先序中的第一个结点
    int index=0;
    while(mid[index]!=ch)//在中序中找到的根结点的左边为该结点的左子树,右边为右子树
    {
        index++;
    }
    BiTree T=new BiTNode;//创建根结点
    T->data=ch;
    T->lchild=pre_mid_createBiTree(pre+1,mid,index);//建立左子树
    T->rchild=pre_mid_createBiTree(pre+index+1,mid+index+1,len-index-1);//建立右子树
    return T;
}

BiTree pro_mid_createBiTree(char *last,char *mid,int len)//后序中序还原建立二叉树
{
    if(len==0)
       return NULL;
    char ch=last[len-1]; //取得后序遍历顺序中最后一个结点
    int index=0;//在中序序列中找根结点,并用index记录长度
    while(mid[index]!=ch)//在中序中找到根结点,左边为该结点的左子树,右边为右子树
       index++;
    BiTree T=new BiTNode;//创建根结点
    T->data=ch;
    T->lchild=pro_mid_createBiTree(last,mid,index);//建立左子树
    T->rchild=pro_mid_createBiTree(last+index,mid+index+1,len-index-1);//建立右子树
    return T;
}

void pre_order(BiTree T)//前序递归遍历二叉树
{
    if(T)
    {
        cout<<T->data;
        pre_order(T->lchild);
        pre_order(T->rchild);
    }
}

void pro_order(BiTree T)//后序递归遍历二叉树
{
    if(T)
    {
        pro_order(T->lchild);
        pro_order(T->rchild);
        cout<<T->data;
    }
}
int main()
{
    BiTree T;
    int n;
    char pre[100],mid[100],last[100];
    cout<<"1. 前序中序还原二叉树\n";
	cout<<"2. 后序中序还原二叉树\n";
	cout<<"0. 退出\n";
	int choose=-1;
	while(choose!=0)
	{
	    cout<<"请选择:";
		cin>>choose;

		switch (choose)
		{
		    case 1://前序中序还原二叉树
		        cout<<"请输入结点的个数:"<<endl;
		        cin>>n;
		        cout<<"请输入前序序列:"<<endl;
		        for(int i=0;i<n;i++)
                    cin>>pre[i];
                cout<<"请输入中序序列:"<<endl;
                for(int i=0;i<n;i++)
                    cin>>mid[i];
                T=pre_mid_createBiTree(pre,mid,n);
                cout<<endl;
                cout<<"二叉树还原成功,输出其后序序列:"<<endl;
                pro_order(T);
                cout<<endl<<endl;
                break;
            case 2://后序中序还原二叉树
                cout<<"请输入结点的个数:"<<endl;
		        cin>>n;
                cout<<"请输入后序序列:"<<endl;
                for(int i=0 ;i<n;i++)
                    cin>>last[i];
                cout<<"请输入中序序列:"<<endl;
                for(int i=0 ;i<n;i++)
                    cin>>mid[i];
                T=pro_mid_createBiTree(last,mid,n);
                cout<<endl;
                cout<<"二叉树还原成功,输出其先序序列:"<<endl;
                pre_order(T);
                cout<<endl<<endl;
                break;
		}
	}
    return 0;
}

运行结果
在这里插入图片描述
在这里插入图片描述

2.求叶子数和节点数
#include <iostream>
using namespace std;

typedef struct Bnode	/*定义二叉树存储结构*/
{ char data;
  struct Bnode *lchild,*rchild;
}Bnode,*Btree;

void Createtree(Btree &T)	/*创建二叉树函数*/
{
    //按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
	char ch;
	cin >> ch;
	if(ch=='#')
        T=NULL;			//递归结束,建空树
	else{
		T=new Bnode;
		T->data=ch;					//生成根结点
		Createtree(T->lchild);	//递归创建左子树
		Createtree(T->rchild);	//递归创建右子树
	}
}

int LeafCount(Btree T)//求二叉树的叶子数
{
    if(T==NULL)//如果为空树,深度为0
        return 0;
    else
        if(T->lchild==NULL&&T->rchild==NULL)//左右子树均为空,则叶子数为1
           return 1;
        else
           return LeafCount(T->lchild)+LeafCount(T->rchild);//递归计算左子树和右子树的叶子数之和
}

int NodeCount(Btree T)//求二叉树的结点数
{
    if(T==NULL)//如果为空树,深度为0
        return 0;
    else
        return NodeCount(T->lchild)+NodeCount(T->rchild)+1;//递归计算左子树和右子树的结点数之和加1
}

int main()
{
    Btree mytree;
    cout<<"按先序次序输入二叉树中结点的值(孩子为空时输入#),创建一棵二叉树"<<endl;
    //ABD##E##CF#G###
    Createtree(mytree);//创建二叉树
    cout<<endl;
    cout<<"二叉树的结点数为:"<<NodeCount(mytree)<<endl;
    cout<<"二叉树的叶子数为:"<<LeafCount(mytree)<<endl;
    return 0;
}
3.求二叉树的深度
#include <iostream>
using namespace std;

typedef struct Bnode	/*定义二叉树存储结构*/
{ char data;
  struct Bnode *lchild,*rchild;
}Bnode,*Btree;

void Createtree(Btree &T)	/*创建二叉树函数*/
{
    //按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
	char ch;
	cin >> ch;
	if(ch=='#')
        T=NULL;			//递归结束,建空树
	else{
		T=new Bnode;
		T->data=ch;					//生成根结点
		Createtree(T->lchild);	//递归创建左子树
		Createtree(T->rchild);	//递归创建右子树
	}
}

int Depth(Btree T)//求二叉树的深度
{
    int m,n;
    if(T==NULL)//如果为空树,深度为0
        return 0;
    else
    {
       m=Depth(T->lchild);//递归计算左子树深度
       n=Depth(T->rchild);//递归计算左子树深度
       if(m>n)
          return m+1;//返回左右子树最大值加1
       else
          return n+1;
    }
}

int main()
{
    Btree mytree;
    cout<<"按先序次序输入二叉树中结点的值(孩子为空时输入#),创建一棵二叉树"<<endl;
    //ABD##E##CF#G###
    Createtree(mytree);//创建二叉树
    cout<<endl;
    cout<<"二叉树的深度为:"<<Depth(mytree)<<endl;
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
5.1 数的逻辑结构 5.1.1 1、的定义 在中常常将数据元素称为结点 (1)有且仅有一个特定的称为根的结点; (2)当n>1时,除根结点之外的其余结点被分成m(m>0)个互不相交的有限合T1,T2,•••Tm,其中每个合又是一棵,并称为这个节点的子。 2、的基本术语: 结点的度、的度 叶子节点、分支结点 孩子节点、分支结点、兄弟节点 路径、路径长度 祖先、子孙 结点的层数、的深度(高度) 层序编号 有序、无序 森林 5.1.2 的抽象数据类型定义 5.1.3的遍历操作 1、前序遍历 的前序遍历操作定义为: 若为空,则空操作返回;否则 (1)访问根结点 (2)按照从左向右的顺序前序遍历根结点的每一棵子。 2、中序遍历 的中序遍历操作定义为: 若为空,则空操作返回;否则 (1)按照从左向右的顺序后序遍历根结点的每一棵子; (2)访问根结点。 3、层序遍历 的层序遍历也称作的广泛遍历,其操作定义为的第一层开始,自上而下逐层遍历,在同一层中,按从左向右的顺序对结点逐个访问。 5.2的存储结构 5.2.1 双亲表示法 由的定义可知,中每个结点都有且仅有一个双亲结点。所以利用这一特性,可以用一维数组来存储各个结点,数组中一个元素对应一个结点,数组元素包括结点的数据信息以及该结点的双亲在数组中的下标。 其中: Data为数据域,存储结点的数据信息; Parent为指针即游标,存储该结点的双亲在数组中的小标。 5.2.2孩子表示法 1、多重链表表示法 (1)指针域的个数等于该结点的度。 (2)指针域的个数等于的度。 2、孩子链表表示法 把孩子看成一个线性表,且以单链表存储,称为该结点的孩子链表。则n个结点有n个孩子链表。 孩子节点有两类:孩子节点、表头结点。 5.2.3 双亲孩子表示法 即将双亲表示法和孩子链表表示法相结合的存储方法。仍将各结点的孩子分别组成单链表,同时用一维数组顺序存储中的各结点,数组元素除了包括结点的数据信息和该结点的孩子链表的头指针之外,还增设一个域存储该结点的双亲在数组的下标。 5.2.4孩子兄弟表示法 又称二链表表示法,其方法是链表中每个结点除数据域外,还设置了两个指针分别指向该结点的第一个孩子和右兄弟链表的结构: Firstchild data rightsib 指针域,存储第一个孩子结点的存储地址 数据域,存储该结点的数据信息 指针域,存储该结点右兄弟结点的存储地址 5.3二叉树的逻辑结构 最简单的树结构,特别适合计算机处理,而且任何数都可以简单的转换为二叉树。(重点内容) 5.3.1二叉树的定义 二叉树是n(n>=0)个结点有限合,该合或者为空,或者有一个根节点和两棵互不相交的、分别称为根节点的左子和右子二叉树组成。 二叉树具有五种基本形态: 1、空二叉树; 2、只有一个根结点; 3、根结点只有左子; 4、根结点只有右子; 5、根结点既有左子又有右子 特殊二叉树: 1、斜; 2、满二叉树; 3、完全二叉树; 5.3.2二叉树的基本性质 性质5-1 二叉树的第i层上最多有2^(i-1)个结点(i>=1)。 性质5-2 在一棵深度为k的二叉树中,最多有2^k-1个结点,最少有k个结点。 性质5-3 在一棵二叉树中,如果叶子结点的个数为n0,度为2的结点个数为n2,则n0=n2+1. 性质5-4 具有n个结点的完全二叉树的深度为【log2^n】+1。 性质5-5 对一棵具有n个结点的完全二叉树中的结点从一开始按层序编号,则对于任意的编号为i(1<=i<=n)的结点,有: (1)如果i>1,则结点i的双亲的编号为【i/2】;否则结点i是根结点,无双亲。 (2)如果2i<=n,则 结点i的左孩子的编号为2i;否则结点i无左孩子。 (3)如果2i+1<=n,则结点i的右孩子的编号为2i+1,否则结点i无右孩子。 5.3.3 二叉树的抽象数据类型定义 同类似,在不同的应用中,二叉树的基本操作不尽相同。 5.3.4 二叉树的遍历操作 二叉树的遍历是指从根节点出发,按照某种次序访问二叉树是所有结点,使得每个结点被访问一次且仅被访问一次。由于二叉树中每个结点都可能有两个子,因此需要寻找一条合适的搜索路径。 1、前序遍历 前序遍历二叉树操作定义为: 若为空,则空操作返回;否则 (1)访问根结点 (2)前序遍历根结点的左子 (3)前序遍历根结点的右子 2、中序遍历 中序遍历二叉树操作定义为: 若为空,则空操作返回;否则 (1)中序遍历根结点的左子 (2)访问根结点 (3)中序遍历根结点的右子 3、后序遍历 后序遍历根结点的左子 后序遍历根结点的右子 访问根结点 4、层序遍历 二叉树的层序遍历是指从二叉树的第一层开始,从上之下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。 5.4 二叉树存储结构及实现 5.4.1 顺序存储结构 具体步骤: (1)将二叉树按完全二叉树编号。 (2)将二叉树中的结点一编号顺序存储到一维数组中。 5.4.2 二叉链表 基本思想: 令二叉树的每个结点对应一个链表结点,链表结点除了存放于二叉树结点有关的数据信息外,还要设置指示左右孩子的指针。 5.4.3 三叉链表 在二叉链表存储方式下,从某个结点出发可以直接访问它的孩子结点,但要找到它的双亲结点,则需要从根节点开始搜索,最坏的情况下,需要遍历整个二叉链表。此时采用三叉链表储存二叉树。 其中,data,lchild,rchild三个域的含义同二叉树,parent域为指向该结点的双亲结点指针。 5.4.4 线索链表 按照某种遍历次序对二叉树进行遍历,可以把二叉树中所有结点排成一个线性序列。在体应用中,有时需要访问二叉树中的结点在某种遍历序列中前驱和后继,此时,在存储结构中应该保存结点在某种遍历序列中的前驱和后继信息。 前驱和后继结点的指针称为线索,加上线索的二叉树称为线索二叉树,加上线索的二叉链表称为线索链表。 5.5 二叉树遍历的非递归算法 5.5.1 前序遍历非递归算法 关键:在前序遍历过某个左子后,如何找到该结点的右子的根指针。 一般的前序遍历执行过程中,设要遍历二叉树的根指针为bt,可能出现两种情况: (1)若bt!=NULL,则表明当前二叉树不为空,此时,应输入根结点bt的值并将bt保存到栈中,准备继续遍历bt的左子。 (2)若bt=NULL,则表明以bt为根指针的二叉树遍历完毕,并且bt是栈顶指针所指结点的左子,若栈不空,则应根据栈顶指针所指结点找到待遍历右子的根指针并赋予bt,以继续遍历下去;若栈空,则表明整个二叉树遍历完毕。 5.5.2 中序遍历非递归算法 此算法只是需要将前序遍历的非递归算法中输出的语句cout<<bt->data移到bt=s[top--]之后即可。 5.5.3 后序遍历非递归算法 后序遍历的不同在于:结点要出入两次栈,出两次栈,这种情况的含义和处理方法为: (1)第一次出栈:只遍历晚左子,右子尚未遍历,则该结点不出栈,利用栈顶结点找到它的右子,准备遍历它的右子。 (2)第二次出栈:遍历完右子,该结点出栈,并访问它。 设根指针为bt,则可能有以下两种情况: (1)若bt!=NULL,则bt及标志flag入栈,遍历其左子。 (2)若bt=NULL,此时栈空,则整个遍历结束;若栈不空,则表明栈顶结点的左子或右子已遍历结束。若栈顶点的标志flag=1,则表明栈结点的左子已遍历完毕,将flag修改为2,修改为2,并遍历栈定点的右子;若栈顶结点的标志flag=2,则表明栈结点的右子也遍历完毕,输出栈顶结点。 5.6 、森林与二叉树的转换 1.转换为二叉树 将一棵转换为二叉树的方法为: (1)加线——中所有相邻的兄弟结点之间加一条线; (2)去线——对中的每个节点,只保留它与第一个孩子结点之间的连线,删去它与其他孩子结点之间的连线。 (3)层次调节——以根结点为轴心,将顺时针转动一定角度,使之层次分明。 2.森林转换成二叉树 (1)将森林中的每一棵二叉树转化成二叉树; (2)从第二课二叉树开始,依次把后一棵二叉树的根结点作为一棵二叉树根节点的右孩子,当所有二叉树连起来后,此时所得到的二叉树就是由森林转换得到的二叉树。 3、二叉树转换为或森林 (1)加线——若某个结点x是其双亲y的左孩子,则把结点x的右孩子、右孩子的右孩子、……,都与结点y用线连起来; (2)去线——删去原二叉树中所有的双亲结点与右孩子结点的连线; (3)层次调整——整理由(1)、(2)两步所得到的或森林,使之层次分明。 (4)森林的遍历 两种遍历方法;前序遍历后续遍历。 5.7 应用举例 5.7.1 二叉树的应用举例——哈夫曼及哈夫曼编码 1、哈夫曼也称最优二叉树,在实际中有着广泛的应用。 叶子节点的权值 是对叶子结点赋予的一个有意义的数值量。 二叉树的带权路径长度 设二叉树具有n个带权值的叶子节点,从根节点到叶子节点的路径长度与相应的叶子节点权值的乘积之和叫做二叉树的带权路径长度,记为: WPL=EWkLk 哈夫曼 给定一组具有确定权值的叶子结点,可以构造出不同的二叉树,将其中带权值路径长度最小的二叉树称为哈夫曼。 哈夫曼算法基本思想: (1)初始化:由给定的n个权值构造n棵只有一个根结点二叉树,从而得到一个二叉树合。 (2)选取与合并:在F中选取根结点的权值最小的两棵二叉树分别作为左、右子构造一棵新的二叉树,这棵新的二叉树的根结点的权值为其左右子结点的权值之和。 (3)删除与加入:在F中删除作为左、右子的两棵二叉树,并将新建的二叉树加入到F中。 (4)重复(2)(3)两步的操作,当合F只剩下一棵二叉树时这棵二叉树便是哈夫曼。 2、哈夫曼编码 在进行程序设计时,通常给每一个字符记一个单独的代码来表示一组字符,我们称之为编码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱编程的大李子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值