一:内容补充
(一)森林转化
森林转换为二叉树
⑴ 将森林中的每棵树转换成二叉树;
⑵ 从第二棵二叉树开始,
依次把后一棵二叉树的根结点作为前一棵二叉树根结点的右孩子,
当所有二叉树连起来后,此时所得到的二叉树就是由森林转换得到的二叉树。
二叉树转换为树或森林
⑴ 加线——若某结点x是其双亲y的左孩子,则把结点x的右孩子、右孩子的右孩子、……,都与结点y用线连起来;
⑵ 去线——删去原二叉树中所有的双亲结点与右孩子结点的连线;
⑶ 层次调整——整理由⑴、⑵两步所得到的树或森林,使之层次分明。
森林有两种遍历方法:
⑴前序(根)遍历:前序遍历森林即为前序遍历森林中的每一棵树。
⑵后序(根)遍历:后序遍历森林即为后序遍历森林中的每一棵树。
叶子结点的权值:对叶子结点赋予的一个有意义的数值量。
二叉树的带权路径长度:设二叉树具有n个带权值的叶子结点,从根结点到各个叶子结点的路径长度与相应叶子结点权值的乘积之和。
(二)哈夫曼树
1)哈夫曼树:给定一组具有确定权值的叶子结点,带权路径长度最小的二叉树。
2)哈夫曼树的特点:
- 权值越大的叶子结点越靠近根结点,而权值越小的叶子结点越远离根结点。
- 只有度为0(叶子结点)和度为2(分支结点)的结点,不存在度为1的结点.
3)哈夫曼算法基本思想:
⑴ 初始化:由给定的n个权值{w1,w2,…,wn}构造n棵只有一个根结点的二叉树,从而得到一个二叉树集合F={T1,T2,…,Tn};
⑵ 选取与合并:在F中选取根结点的权值最小的两棵二叉树分别作为左、右子树构造一棵新的二叉树,这棵新二叉树的根结点的权值为其左、右子树根结点的权值之和;
⑶ 删除与加入:在F中删除作为左、右子树的两棵二叉树,并将新建立的二叉树加入到F中;
⑷ 重复⑵、⑶两步,当集合F中只剩下一棵二叉树时,这棵二叉树便是哈夫曼树。
哈夫曼编码:
编码:给每一个对象标记一个二进制位串来表示一组对象。
例:ASCII,指令系统
等长编码:表示一组对象的二进制位串的长度相等。
不等长编码:表示一组对象的二进制位串的长度不相等。
前缀编码:一组编码中任一编码都不是其它任何一个编码的前缀 。
前缀编码保证了在解码时不会有多种可能。
(三)线索链表
线索:将二叉链表中的空指针域指向前驱结点和后继结点的指针被称为线索;
线索化:使二叉链表中结点的空链域存放其前驱或后继信息的过程称为线索化;
线索二叉树:加上线索的二叉树称为线索二叉树。
二叉树的遍历方式有4种,故有4种意义下的前驱和后继,相应的有4种线索二叉树:
⑴ 前序线索二叉树
⑵ 中序线索二叉树
⑶ 后序线索二叉树
⑷ 层序线索二叉树
二:
例题
1.采用二叉链表的方式进行存储
2.构造一个二叉树类
实现以下算法:
1.创建二叉树
2.对二叉树进行前序、中序、后序遍历
#include<bits/stdc++.h>
using namespace std;
struct node
{
char data;
node *lchild,*rchild;
};
class Tree
{
public:
Tree(){root=Creat();}
~Tree(){release(root);}
void firstly(){firstly(root);}
void midly(){midly(root);}
void last(){last(root);}
//void level();
private:
node *Creat();
void release(node *bt);
void firstly(node *bt);
void midly(node *bt);
void last(node *bt);
node root;
};
nodeTree::Creat()//构造函数
{
node *bt;
char ch;
cin>>ch;
if(ch==’#’) bt=NULL;
else
{
bt=new node;
bt->data=ch;
bt->lchild=Creat();
bt->rchild=Creat();
}
return bt;
}
void Tree::firstly(node *bt)//前序遍历
{
if(btNULL) return;
else
{
cout<data;
firstly(bt->lchild);
firstly(bt->rchild);
}
}
void Tree::midly(node *bt)//中序遍历
{
if(btNULL) return;
else
{
midly(bt->lchild);
cout<data;
midly(bt->rchild);
}
}
void Tree::last(node *bt)//后序遍历
{
if(btNULL) return;
else
{
last(bt->lchild);
last(bt->rchild);
cout<data;
}
}
void Tree::release(node *bt)//析构函数
{
if(btNULL) return;
else
{
release(bt->lchild);
release(bt->rchild);
delete bt;
}
}
int Tree::Count(node *bt)//节点数
{
int number=0;
if(btNULL)
number=0;
else
number=Count(bt->lchild)+Count(bt->rchild)+1;
return number;
}
int Tree::leaf(node *bt)//叶子节点数
{
int number=0;
if(btNULL)
number=0;
else if(bt->lchildNULL&&bt->rchildNULL)
number=1;
else
number=leaf(bt->lchild)+leaf(bt->rchild);
return number;
}
int Tree::height(node *bt)//树的高度
{
int lheight=0,rheight=0;
if(bt==NULL)
return 0;
lheight=height(bt->lchild);
rheight=height(bt->rchild);
if(lheight>rheight)
return lheight+1;
else
return rheight+1;
}