二叉树(binary_tree)

1.树的概念

树(tree)是一种数据结构,不同于线性数据结构,它属于树形数据结构,如同它的名字一样,它就和现实中的树类似,例如:

这棵树拥有14个节点,共4层,为一棵三叉树;

他很像现实中的树倒转过来一样,顶层为根,中间为树枝,地下为叶子,分别称为根节点中间节点叶子节点

树结点的概念

一个节点有以下几个概念:

(1).父节点

一个节点(除了根节点)的父节点就是它上面一层的与它直接相连的节点,一个节点有且仅有一个父节点;

(2).子节点

一个节点(除了叶子节点)的子节点就是它下面一层的与它直接相连的节点,一个节点可能有多个子结点,也有可能没有子节点(叶子节点);

(3).根节点

根节点是唯一的一个没有父节点的节点,他是一棵树组成的基本,任何非空树的树都必须有根节点(空树没有节点);

(4).叶子节点

叶子节点可以有任意多个,它们没有子节点,是一棵树组成的基本,特别的,只有一个节点的树的根节点也是叶子节点;

2.二叉树的概念

(1).二叉树的构造

二叉树(binary_tree),这种树每个节点最多只有两个分叉,它是许多高级数据结构的基础,例如线段树平衡树树套树等等,是数据结构重要的一环;

二叉树其实就相当于一个树状的链表,可以这样构造:

struct node{
    int value;
    node *father, *left_son, *right_son;
};

不难发现,这与链表有异曲同工之妙,只是将一对一变成了一对多而已;

(2).完全二叉树

完全二叉树就是一种可以用数组存储的二叉树,它的叶子节点都在最后两行,最后一行的叶子节点在倒数第二行的左边;

例如:

它可以这样存储:

int tree[Max_tree_number]; // 树

tree[this_node] // 当前节点

tree[this_node << 1] // 左子节点

tree[(this_node << 1) + 1] // 右子节点
(3).满二叉树

满二叉树特殊的完全二叉树,它的叶子节点都在最后一层,它的节点正好是2^n-1个,它也是一棵平衡二叉树

3.二叉树的遍历

二叉树的遍历有四种,分别是先序遍历中序遍历后序遍历层序遍历

注:前三种遍历方式的代码十分相似,只是在递归代码中输出的位置不同:

void dfs(int node){
    // 先序遍历
    dfs(node << 1);
    // 中序遍历
    dfs((node << 1) + 1);
    // 后序遍历
}
(1).先序遍历

先序遍历遵守根左右的规则,例如:

这棵树的先序遍历为:

1,2,4,8,9,5,10,11,3,6,7

(2).中序遍历

中序遍历遵守左根右的规则,例如上图:

这棵树的中序遍历为:

8,4,9,2,10,5,11,1,6,3,7

(3).后序遍历

后序遍历遵守左右根的规则,例如上图:

这棵树的后序遍历为:

8,9,4,10,11,5,2,6,7,3,1

(4).层序遍历

层序遍历遵守广度优先搜索(BFS)的规则,例如上图:

这棵树的层序遍历为:

1,2,3,4,5,6,7,8,9,10,11

(5).表达式树

一串表达式可以构成一个特殊的树——表达式树;

例如这串表达式:

3 + 7 \times 10 - 6 \div 2

构成的表达式树为:

可以通过先序遍历中序遍历和后序遍历来构造前缀表达式(波兰式)中缀表达式后缀表达式(逆波兰式)

(6).前缀表达式(波兰式)

前缀表达式(波兰式)是通过先序遍历构成的,例如上图,构成的前缀表达式为:

+\ 3\ -\ \times\ 7\ 10\ \div\ 6\ 2

(7).中缀表达式

中缀表达式是通过中序遍历构成的,例如上图,构成的中缀表达式为:

3 + 7 \times 10 - 6 \div 2

可以发现,中缀表达式就是我们平常用的算式;

(8).后缀表达式(逆波兰式)

后缀表达式(逆波兰式)是通过后序遍历构成的,例如上图,构成的后缀表达式为:

3\ 7\ 10\ \times\ 6\ 2\ \div\ -\ +

(9).前缀表达式与后缀表达式的用处

前缀表达式后缀表达式一般适用于计算机,由于这两个表达式不需要括号,所以可以用来实现;

4.二叉树的深度优先搜索与广度优先搜索

(1).二叉树的深度优先搜索

二叉树的深度优先搜索(DFS,简称深搜)一般是求先序遍历中序遍历或者后序遍历

深度优先搜索的逻辑为:一直往下搜,直到没有路为止,然后回溯,继续找路;

注:第3节已经给了代码,这里不过多赘述;

(2).二叉树的广度优先搜索

二叉树的广度优先搜索(BFS,简称广搜,也称宽度优先搜索,简称宽搜)一般是求层序遍历,大多数情况下是没有什么意义的;

广度优先搜索的逻辑为:每搜到一个节点就回头再找上一轮的节点继续搜索,和火灾蔓延相似;

广度优先搜索需要使用队列来遍历:

queue<node> the_queue; // STL

void bfs(){
    the_queue.push(root);
    while(!the_queue.empty()){
        if(the_queue.front().left != NULL)
            the_queue.push(the_queue.front().left);
        if(the_queue.front().right != NULL)
            the_queue.push(the_queue.front().right);
        the_queue.pop();
    }
}

注:此代码仅二叉树可用;

5.哈夫曼树(待更新)

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值