【数据结构】树与二叉树

1 易错概念

  • 树中的度不同于图中的度,树中的度指出度(子树数目),而图中的度指总度数(出+入)
  • 叶结点是指度数为0的结点,也称为终端结点
  • 树的度指树中所有结点度的最大值

2 二叉树的数学性质

  • 二叉树的第i层上最多有 2 n − 1 2^{n-1} 2n1个结点
  • 深度为k的二叉树最多有 2 k − 1 2^{k}-1 2k1个结点
  • 对任意一棵二叉树T,叶结点数为 n 0 n_0 n0,度数为2的结点数为 n 1 n_1 n1,则 n 0 = n 2 + 1. n_0=n_2+1. n0=n2+1.
    证明: 总 结 点 = n 0 + n 1 + n 2 . 总 边 数 = n 1 + 2 n 2 . 总 结 点 = 总 边 数 + 1 , n 0 + n 1 + n 2 = n 1 + 2 n 2 + 1. 总结点=n_0+n_1+n_2. 总边数=n_1+2n_2.总结点=总边数+1,n_0+n_1+n_2=n_1+2n_2+1. =n0+n1+n2.=n1+2n2.=+1n0+n1+n2=n1+2n2+1.
  • 具有n个结点的完全二叉树深度为: l o g 2 n + 1. log_2n+1. log2n+1.
    在这里插入图片描述

3 特殊二叉树

  • 满二叉树
  • 完全二叉树

4 树的存储结构

  • 顺序存储结构——空间浪费问题
  • 链式存储结构
typedef struct Node{
	DataType data;
	struct Node *LChild;
	struct Node *RChild;
}BiTNode,*BiTree;

一个二叉树有n个结点,则有2n个链域,其中有n+1个空链域(非空链域:n-1 出边数)

5 二叉树的遍历

  • 前序遍历
void PreOrder(BiTree root){
	if(root!=NULL){
		Visit(root->data);
		PreOrder(root->LChild);
		PreOrder(root->RChild);
	}
}
  • 中序遍历
void InOrder(BiTree root){
	if(root!=NULL){
		InOrder(root->LChild);
		Visit(root->data);
		InOrder(root->RChild);
	}
}
  • 后序遍历
void PostOrder(BiTree root){
	if(root!=NULL){
		PostOrder(root->LChild);
		PostOrder(root->RChild);
		Visit(root->data);
	}
}

6 表达式求值

  • 前缀表达式 (波兰表达式)
  • 中缀表达式 (常用表达式)
  • 后缀表达式 (逆波兰)

这三者可以相互转换,比如从中缀表达式到前缀和后缀即是按运算顺序加括号,然后将所有的运算符移动到前面或后面,最后去掉括号的过程。

7 输出二叉树结点

void PrintPreOrder(BiTree root){
    if(root!=NULL){
        if(root->LChild==NULL&&root->RChild==NULL){
            cout<<root->data<<" ";
        }
        PreOrder(root->LChild);
        PreOrder(root->RChild);
    }
}

8 统计叶结点数

void leafnum(BiTree root){
    if(root!=NULL){
        leafnum(root->LChild);
        leafnum(root->RChild);
        if(root->LChild==NULL&&root->RChild==NULL) leafcnt++;
    }
}

分治法:

void leafnum(BiTree root){
    int leafcnt;
    if(root==NULL) leafcnt=0;
    else{
        if(root->LChild==NULL&&root->RChild==NULL) leafcnt=1;
        else leafcnt=leafnum(root->LChild)+leafnum(root->RChild);
    }
    return leafcnt;
}

9 树的高度

后序遍历:
从根结点的左右子树开始递归计算,分别算出hl和hr后取较大的加一

int PostTreeDepth(BiTree bt){
    int hl,hr,max;
    if(bt!=NULL){
        hl=PostTreeDepth(bt->LChild);
        hr=PostTreeDepth(bt->LChild);
        max=hl>hr?hl:hr; //取左右子树深度较大的
        return (max+1); //加上根结点
    }
}

先序遍历,往下走层次加一,更新深度

void PreTreeDepth(BiTree bt,int h){
    //h是当前层次,初始为1
    //depth记录最大层次 初始为0
    if(bt!=NULL){
        if(h>depth) depth=h;
        PreTreeDepth(bt->LChild,h+1);
        PreTreeDepth(bt->RChild,h+1);
    }
}

10 中序遍历的非递归算法

void InOrder(BiTree root){
    InitStack(&S);
    p=root;
    while(p!=NULL||!IsEmpty(S)){
        if(p!=NULL){
            Push(&S,p);
            p=p->LChild;
        }else{
            Pop(&S,&p);
            Visit(p->data);
            p=p->RChild;
        }
    }
}

11 二叉树的线索化

线索化的过程是在遍历过程中修改空指针的过程

12 由遍历序列确定二叉树

参见我的总结:通过遍历结果推二叉树的构造

重重点!

  • 前序遍历的第一个元素可以确定根结点
  • 后续遍历的最后一个元素可以确定根结点
  • 确定了根节点后,通过中序遍历对左右子树进行划分
  • 重复上述过程,找根结点并划分左右子树,递归处理,最终得到一棵完整的二叉树
  • 另外,一定需要中序才能确定一棵二叉树

13 树 森林与二叉树

树的三种表示方式

  • 双亲表示法
  • 孩子表示法
  • 孩子兄弟表示法 左孩子右兄弟

− > -> > 森林

图中三个步骤即可!
在这里插入图片描述

森林 − > -> > 二叉树

先通过上述方法将树转二叉树,然后下一棵树的根结点作为上一颗树的右孩子组合在一起即可!
在这里插入图片描述

二叉树还原为树和森林

在这里插入图片描述

树的遍历

  • 先根遍历
  • 后根遍历

森林的遍历

  • 先序遍历
  • 中序遍历
  • 后序遍历

14 哈夫曼树

带权路径最短二叉树!
选取最小的两个结点组合,在将这两个结点的和加入原序列中,继续选取最小的两个结点,递归组合成为一棵哈夫曼树(直观看,权重大的结点靠近根结点)

15 并查集

16 层次遍历二叉树

本文更新至2020.8.1


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mr.zwX

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

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

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

打赏作者

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

抵扣说明:

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

余额充值