高级数据结构之二叉树

一、二叉树的分类和其性质

  1. 二叉树的第 i i 层最多有2(i-1)个结点。
  2. 满二叉树:所有层的节点都是满的。一个 n n 层的二叉树,共有 2 n 1 2^n-1 个结点。
  3. 完全二叉树:仅在最后一层有缺失结点,但缺失的结点编号都在最后。

二、完全二叉树的性质

在这里插入图片描述
设节点数量为 k k ,1号为根节点, i i 为编号。

  1. i > 1 i>1 的结点,其父节点是 i / 2 i/2 ;
  2. 2 i > k 2*i>k ,则 i i 没有孩子;若 2 i + 1 > k 2*i+1>k ,则 i i 没有右孩子。
  3. i i有孩子 ,则左孩子为 2 i 2*i ,右孩子为 2 i + 1 2*i+1

三、二叉树的储存

1、指针实现:

struct node
{
    string value;   //结点值
    node *l, *r; //指向左右结点
    node()       //初始化
    {
        l = r = NULL;
    }
};

新建一个node时,用new运算符动态申请内存。结束时,用delete释放内存。

2、数组实现:

//利用i的左结点是2*i,右结点是2*i+1.
int heap[MAXN];

四、二叉树的遍历

我们有两种搜索方式,dfsbfs遍历二叉树,这时候根据题干的要求来选择对应的遍历方式。

1、bfs—广度优先搜索

利用队列实现。

2、dfs—深度优先搜索

这时候分为三种遍历方式:先序遍历中序遍历后续遍历
先、中、后代表的是根结点的相对位置。

①:先序遍历

遍历顺序: 父节点、左儿子、右儿子。
伪代码:

void pre_order(node *root) //先序遍历
{
    if (root != NULL) //根据题干来添加判断,并进行输出和递归
    {
        cout << root->value << endl; //输出结点值
        pre_order(root->l);           //递归左子树
        pre_order(root->r);           //递归右子树
    }
}

图示:
在这里插入图片描述

②:中序遍历

遍历顺序 :左儿子、父结点、右儿子。
性质、特征:

  1. 二叉搜索树中,中序遍历实现了排序的功能,返回的结果是有序的。
  2. 若根结点已知,返回的结果中,排在根结点左端的序列在左子树上,排在根结点右端的序列在右子树上。

伪代码:

void in_order(node *root) //中序遍历
{
    if (root != NULL) //根据题干来添加判断,并进行输出和递归
    {
        in_order(root->l);            //递归左子树
        cout << root->value << endl; //输出结点值
        in_order(root->r);            //递归右子树
    }
}

图示:
在这里插入图片描述


③:后序遍历

遍历顺序:左儿子、右儿子、父结点。
后序遍历的最后一个结点是树的根。
伪代码:

void post_order(node *root) //后序遍历
{
    if (root != NULL) //根据题干来添加判断,并进行输出和递归
    {
        post_order(root->l);            //递归左子树
        post_order(root->r);            //递归右子树
        cout << root->value << endl; //输出结点值
    }
}

图示:
在这里插入图片描述


④:利用两种两种不同的已知遍历顺序来确定一棵树

先序+中序或者中序+后序。但是先序+后序不能确定一棵树

例题P1030 求先序排列
ACcode:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
char in_order[15], post_order[15];
int len;
void dfs(int in_l, int in_r, int post_l, int post_r)
{
    for (int i = in_l; i <= in_r; i++) //中序遍历
    {
        if (post_order[post_r] == in_order[i])
        {
            cout << in_order[i];
            dfs(in_l, i - 1, post_l, post_l + (i - in_l - 1)); //左儿子
            dfs(i + 1, in_r, post_l + (i - in_l), post_r - 1); //右儿子
            return;
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin >> in_order;
    cin >> post_order;
    len = strlen(in_order);
    dfs(0, len - 1, 0, len - 1);
    cout << endl;
    return 0;
}

五、二叉树的生成和二叉树的释放空间

1、二叉树的生成:

步骤:
先序遍历输入要生成的二叉树数据,#代表空结点 。
伪代码:

void create_tree(node *&root)
{
    char ch;
    cin >> ch; //输入先序遍历
    if (ch != '#')
    {
        root = new node;      //动态申请内存
        root->value = ch;     //读入
        create_tree(root->l); //建立左子树
        create_tree(root->r); //建立右子树
    }
}

2、二叉树的释放空间:

伪代码:

void remove_tree(node *root) //二叉树的释放空间
{
    if (root == NULL)
        return;
    remove_tree(root->l);
    remove_tree(root->r);
    delete root;
}

六、二叉树结点的查找

若查找成功返回其指针,同样也能改写成bool类型。

node *find_node(node *&root, string aim) //若查找到返回其指针
{
    node *p;
    if (root == NULL) //空树
        return NULL;
    else if (root->value == aim) //找到该值
        return root;
    else //暂时未找到,递归进行查找
    {
        p = find_node(root->l, aim); //递归查找左树
        if (p != NULL)
            return p;
        else
            return find_node(root->r, aim); //递归查找右树
    }
}

七、二叉树高度查询

伪代码:

int high_node(node *root) //二叉树的高度
{
    int l_high, r_high;
    if (root == NULL) //空树
        return 0;
    else
    {
        l_high = high_node(root->l);
        r_high = high_node(root->r);
        return max(l_high + 1, r_high + 1);
    }
}

猜你喜欢

转载自blog.csdn.net/acm_durante/article/details/104734188