数据结构笔记--树和二叉树

基本定义

  • Tree,是n(n≥0)个结点的有限集合。树有且仅有一个特定的称为根root的结点,当n>1时,除根结点的其余结点被分成m(m>00)个不相交的有限集合T1,T2,…,Tm,其中每一个集合又是一棵树,并称为这个根结点的子树。
  • 某结点所拥有子树的个数称为该结点的度,树中各结点度的最大值称为该树的度
  • 度为零的结点称为以叶子结点,度不为零的结点称为分支结点
  • 某结点的子树的根节点称为该结点的孩子结点,该结点称为其孩子结点的双亲结点
  • 规定根节点的层数为1,对其余任何结点,若结点在k层,则其孩子结点在第k+1层;树中所有结点的最大层数称为树的深度
  • m(m≥0)棵互不相交的树的集合构成森林

存储结构

-双亲表示法

const int MaxSize = 10;
typedef int DataType;
typedef struct
{
    DataType data;
    int parent;
} PNode;
typedef struct
{
    PNode Data[MaxSize];
    int treeNum;
} PTree;
  • 孩子表示法
const int MaxSize = 10;
typedef int DataType;
typedef struct CTNode // 定义孩子结点
{
    int child;
    struct CTNode *next;
} CTNode;
Typedef struct       // 定义表头结点
{
    DataType data;
    CTNode *firstchild;
} CBNode;
typedef struct      // 定义孩子表示法
{
    CBNode data[MaxSize];
    int treeNum;
} CTTree;
  • 孩子兄弟表示法
typedef int DataType;
typedef struct TNode
{
    DataType data;;
    struct Tnode *firstchild, *rightsib;
} Tnode;

遍历

  • 前序遍历:访问根节点,按照从左到右的顺序遍历根结点的每一棵子树
  • 后序遍历:按照从左到右的顺序遍历根结点的每一棵子树,访问根结点
  • 层序遍历:广度遍历,从第一层(根结点)开始,自上而下逐层遍历,同一层按照从左到右的顺序遍历

二叉树

基本定义

  • binary tree,是n(n≥0)个结点的有限集合,该集合或为空集或者有一个根结点和两棵互不相交的、分贝称为根节点的左子树和右子树的二叉树组成
  • 每个结点最多有两棵树,二叉树中不存在度大于2的结点
  • 二叉树的左右子树不能颠倒,必须指明左右
  • 所有结点都只有左子树的二叉树称为左斜树,所有结点都只有右子树的二叉树称为右斜树
  • 在一棵二叉树中,如果所有的分支都存在左子树和右子树,并且叶子节点都在同一层上,这样的二叉树称为满二叉树
  • 对一棵具有n个结点的二叉树按层序编号,如果编号为i(1≤i≤n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中的位置完全相同,则这棵二叉树称为完全二叉树

基本性质

  • 二叉树的第i层上最多有2^(i-1)个结点(i≥1)
  • 在一棵深度为k的二叉树中,最多有2^k-1个结点
  • 在一棵二叉树中,如果叶子结点的个数为n0,度为2的结点的个数n2,则n0 = n2 + 1
  • 具有n个结点的完全二叉树的深度为log2(n) + 1

顺序存储结构

  • 按照完全二叉树进行程序编号,使用一维数组进行存储,并不是很常用
const int MaxHigh = 10;
typedef int DataType;
typedef struct
{
    DataType data[2^MaxHigh - 1];
    int biTreeNum;
} SeqBiTree;

二叉链表

  • 一般会采用的存储方式。
  • 基本思想:令二叉树的每个结点对对应一个链表的结点,链表结点除了存放二叉树结点的数据信息外,还要设置指示左右孩子的指针。
    这里写图片描述
  • 存储结构
typedef int DataType;
typedef struct BiNode
{
    DataType Data;
    struct BiNode *lchild, *rchild;
} BiNode, *root;
  • 遍历
// 前序遍历
void PreOrder(BiNode *root)
{
    if(root == NULL) 
        return;
    else {
        printf(root->data);
        PreOrder(root->lchild);
        PreOrder(root->rchild);
    }
}
// 后序遍历
void PostOrder(BiNode *root)
{
    if(root == NULL) 
        return;
    else {
        PreOrder(root->lchild);
        PreOrder(root->rchild);
        printf(root->data);
    }
}
// 层序遍历,使用队列Q
void LevelOrder(BiNode *root)
{
    front=rear = -1;
    if(root == NULL) 
        return;
    Q[++rear] = root;
    while( front != rear ) {
        q = Q[++front];
        printf(q->data);
        if (q->lchild != NULL )
            Q[++rear] = q->lchild;
        if (q->rchild != NULL )
            Q[++rear] = q->rchild;
    }
}
  • 建立算法
// pre[n]、pin[n]中分别保存二叉树的前序序列和中序序列
// pos(x, pin, i)返回数组pin中从第i个元素开始等于x的位置
BiNode* Create(BiNode *root, int i1, int i2, int k)
{
    if(K <= 0)
        root = NULL;
    else {
        root = (BiNode *)malloc(sizeof(BiNode));
        root->data = pre[i1];
        m = pos(pre[i1], pin, i2);
        leftlen = m - i2;
        rightlen = k - (leftlen + 1);
        root->lchild = Creat(root->lchild, i1+1, i2, leftlen);
        root->rchild = Creat(root->rchild, i1+leftlen+1, i2, rightlen);
    }
    return root;
}

三叉链表

  • 在二叉链表的基础上,增加一个parent域来指向该节点的双亲结点
    这里写图片描述

哈弗曼树和哈弗曼编码

基本定义

  • huffman tree,给定一组具有确定权值的叶子节点

todo

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值