赞
踩
树型结构是一类重要的非线性数据结构,其中以树和二叉树最为常用。
树是以分支关系定义的层次结构。
简单粗暴的定义就是有且仅有一个根节点、无环。
要求严格一点
特点:
1.每个结点至多只有两棵子树,即二叉树中的结点度都不大于2;
2.二叉树的子树有左右之分,次序不能任意颠倒;
二叉树的5种基本形态
满二叉树:每一层上的结点数都是最大结点数
完全二叉树:
深度为k的,有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应。
*特点:*叶子结点只在最深的两层出现;
对任一结点若其右分支的最大深度为
l
l
l,则左分支的最大深度必为
l
l
l或
l
+
1
l+1
l+1(可以理解为左子树要全满);
完全二叉树的两个重要特性:
二叉树的二叉链表存储表示
typedef struct BitNode{ int data;//int 可换成其他数据类型 struct BitNode *lchild,*rchild; }BitNode,*BiTree; //创建二叉树 void Create(BiTree *T)//二级指针 指向BiTree的指针 { char ch; scanf("%c",&ch); if(ch=='#')//#代表结点为空 { *T=NULL; return; } (*T)=(BiTree)malloc(sizeof(BitNode)); (*T)->data=ch; Create(&((*T)->lchild));//传递*T的左孩子的地址 Create(&((*T)->rchild));//传递*T的右孩子的地址 }
递归算法定义:
若二叉树为空.则空操作;否则
(1)访问根结点;
(2)先序遍历左子树;
(3)先序遍历右子树。
//先序遍历
void Pre_Traversal(BiTree T)
{
if(T==NULL)return;
printf("%c ",T->data);
Pre_Traversal(T->lchild);
Pre_Traversal(T->rchild);
}
若二叉树为空,则空操作;否则
(1)中序遍历左子树;
(2)访问根结点;
(3)中序遍历右子树。
//中序遍历
void Mid_Traversal(BiTree T)
{
if(T==NULL)return;
Mid_Traversal(T->lchild);
printf("%c ",T->data);
Mid_Traversal(T->rchild);
}
若二叉树为空,则空操作;否则:
(1)后序遍历左子树;
(2)后序遍历右子树;
(3)访问根结点。
//后序遍历
void Post_Traversal(BiTree T)
{
if(T==NULL)return;
Post_Traversal(T->lchild);
Post_Traversal(T->rchild);
printf("%c ",T->data);
}
又称最优树,是一类带权路径最短的树。
树的路径长度是从树根到每一结点的路径长度之和。
结点的带权路径长度为从该结点到树根之间的路径长度与结点上权的乘积。
树的带权路径长度之和为树中所有叶子节点的带权路径长度之和,记作
W
P
L
=
∑
k
=
1
n
w
k
l
k
WPL=\sum_{k=1}^nw_kl_k
WPL=∑k=1nwklk。
假设有 n n n个权值 { w 1 , w 2 , . . . w n } \{w_1,w_2,...w_n\} {w1,w2,...wn},试构造一棵有 n n n个叶子结点的二叉树,每个叶子节点带权为 w i w_i wi,则其中 W P L WPL WPL最小的二叉树称做最优二叉树或哈夫曼树。
哈夫曼算法
具体过程较为直观:
假设有
{
a
,
b
,
c
,
d
}
\{a,b,c,d\}
{a,b,c,d}四个结点,权值分别为
{
7
,
5
,
2
,
4
}
\{7,5,2,4\}
{7,5,2,4},将四个结点都视为只有根结点的树。
1.找到权值最小的两个结点
c
,
d
c,d
c,d,将之构造为一棵树并给根结点赋权值,权值为两结点之和,此时有
{
7
,
5
,
6
}
\{7,5,6\}
{7,5,6};
2.继续寻找根结点权值最小的两棵树并将之合并,新树根结点权值为两树根结点之和;
3.重复以上过程直至最后只剩一棵树,该树即为哈夫曼树,树根结点权值即为
W
P
L
WPL
WPL。
前缀编码:编码长度可以不一,任一个字符的编码都不是另一个字符编码的前缀。
设计电文总长最短的二进制前缀编码,即以 n n n种字符出现的频率作权设计一棵哈夫曼树的问题,得到的前缀编码称为哈夫曼编码。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。