数据结构——树、森林、赫夫曼树




  • 树与森林
1.树的存储结构
(1)双亲表示法:利用每个结点只有一个双亲的性质,在每个结点中附设一个指示器指示其双亲结点在链表中的位置
(2)孩子表示法:把每个孩子结点排列起来,看成是一个线性表,且以单链表作存储结构
(3)孩子兄弟表示法(称为二叉树表示法或者二叉链表表示法)
typedef struct CSNode{
  ElemType          data;
  struct CSNode     *firstchild,*nextsibling;//结点的两个链域分别指向该结点的第一个孩子结点和下一个兄弟结点
}CSNode,*CSTree;
2.森林和二叉树的转换
二叉树和树都可用二叉链表作为存储结构,则以二叉链表作为媒体可导出树与二叉树之间的一个对应关系。
(1)森林转换成二叉树
F={T1,T2,...,Tm}表示森林
B={root,LB,RB}表示二叉树
B的root为森林中第一棵树(T1)的根;左子树LB是T1转换而来的,右子树是剩下的转化而来的。
(2)二叉树转化为森林
T1的根为B的root,其余树为右子树转化而来的
3.森林和树的遍历
遍历树的方法:
(1)先根遍历树:先访问树的根结点,然后依次遍历根的每一棵子树,ABCDE
(2)后根遍历树:先依次遍历每一棵子树,然后访问根结点,BDCEA
森林的两种遍历方法:
(1)先序遍历森林(非空):
  1. 访问森林中第一棵树的根结点
  2. 先序遍历第一棵树中根结点的子树森林
  3. 先序遍历除去第一棵树之后剩余树构成的森林
(2)中序遍历森林(非空):
  1. 中序遍历森林中国第一棵树的根结点的子树森林
  2. 访问第一棵树的根结点
  3. 中序遍历除去第一棵树之后剩余树构成的森林
上述森林的先序和中序可以看成对应二叉树的先序和中序遍历,当以二叉链表作树的存储结构时,树的先根遍历和后根遍历都可借用二叉树的先序遍历和中序遍历算法实现

二叉排序树:二叉排序树(Binary Sort Tree)又称二叉查找树。
若他不为空则具有下列性质的二叉树:     (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; 
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; 
(3)左、右子树也分别为二叉排序树;

//定义一个二叉排序树结构
typedef int DataType;
typedef struct BST_Node {
    DataType data;
    struct BST_Node *lchild, *rchild;
}BST_T, *BST_P;
//建立二叉排序树,用到Insert_BST方法
void CreateBST(BST_P *T, int a[], int n)
{
    int i;
    for (i = 0; i < n; i++)
    {
        Insert_BST(T, a[i]);
    }
}
二叉排序树查找:要在二叉树中找出查找最大最小元素是极简单的事情,从根节点一直往左走,直到无路可走就可得到最小值;从根节点一直往右走,直到无路可走,就可以得到最大值。
二叉排序树插入:插入新元素时,可以从根节点开始,遇键值较大者就向左,遇键值较小者就向右,一直到末端,就是插入点。
二叉排序树删除:(1)如果A只有一个子节点,就直接将A的子节点连至A的父节点上,并将A删除;
      (2)如果A有两个子节点,我们就以右子树内的最小节点取代A,怎么得最小节点,前有有说。

平衡二叉树定义(AVL):若他不是一颗空树则具有以下性质的二叉树:它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树。
平衡因子(bf):结点的左子树的深度减去右子树的深度,那么显然-1<=bf<=1,这里我们定义:
#define EH 0,#define LH 1,#define RH -1.依次为等高,左高,右高。
//定义一个二叉树和他的平衡因子
typedef struct _BitNode
{
     int data;
     int bf;//平衡因子
    struct _BitNode *lchild,*rchild;
}BitNode,*BiTree;
在搜索时,平衡二叉树的速度更快

赫夫曼树:又称最优树,是一类带权路径长度最短的树
赫夫曼算法:
基本思想:使权大的结点靠近根
*   根据给定的n个权值{w1,w2,……wn},构造n棵只有根结点的二叉树。
*   在森林中选取两棵根结点权值最小的树作左右子树,构造一棵新的二叉树,置新二叉树根结点权值为其左右子树根结点权值之和。
*   在森林中删除这两棵树,同时将新得到的二叉树加入森林中。
*   重复上述两步,直到只含一棵树为止,这棵树即赫夫曼树。

赫夫曼编码:
若要设计长短不等的编码,则必须是任一个字符的编码都不是另一个编码的前缀,这种编码称为前缀编码
基本思想:概率大的字符用短码,小的用长码,构造哈夫曼树
例题:

赫夫曼编码的几点结论:
* 赫夫曼编码是不等长编码
* 赫夫曼编码是前缀编码,即任一字符的编码都不是另一字符编码的前缀
* 赫夫曼编码树中没有度为1的结点。若叶子结点的个数为n,则赫夫曼编码树的结点总数为 2n-1
* 发送过程:根据由赫夫曼树得到的编码表送出字符数据
* 接收过程:按左0、右1的规定,从根结点走到一个叶结点,完成一个字符的译码。反复此过程,直到接收数据结束


猜你喜欢

转载自blog.csdn.net/jiechou8218/article/details/79973095
今日推荐