二叉树性质和遍历

二叉树

二叉树性质

  1. 在第n层,最多有 2 n − 1 2^{n-1} 2n1个节点
  2. 深度为n层的二叉树,最多有 2 n − 1 2^{n}-1 2n1个节点
  3. 任何一个二叉树,叶节点有 n 0 n_{0} n0个,度为2的非叶节点有 n 2 n_{2} n2个,那么 n 0 = n 2 + 1 n_{0}=n_{2}+1 n0=n2+1
  4. 具有n个节点的完全二叉树,的高度为 ⌊ l o g 2 n ⌋ + 1 \lfloor log_{2}n \rfloor +1 log2n+1 ⌊ ⌋ \lfloor\rfloor 表示向下取整

二叉树遍历

  • 前序遍历:中左右
  • 中序遍历:左中右
  • 后序遍历:左右中

递归方式

在这里插入图片描述
如果用递归方式,那么遍历顺序是固定的,打印节点的时间决定了是那种遍历。拿上图来说,对于F左侧,顺序是FCA(A左子树为空)A(A右子树为空)ACDB(B左子树为空)D…

  • 前序遍历:在第一次进入打印节点
  • 中序遍历:第二次打印节点
  • 后序遍历:第三次打印节点

代码

#include <iostream>
#include <stdlib.h>

//节点
struct Node {
    int value;
    Node* left;
    Node* right;

    Node(int v = 0): value(v), left(nullptr), right(nullptr) {}
};

//向二叉树插入元素
void insert_tree(Node* &root, int value) {
    if (nullptr == root) {
        root = new Node(value);
        return;
    }
    if (value < root->value) {
        insert_tree(root->left, value);
    } else if (value > root->value) {
        insert_tree(root->right, value);
    }
}

//生成二叉树
void create_tree(Node* root, int root_value, int size) {
    root->value = root_value++;
    for (int i = 0; i <= size; ++i) {
        insert_tree(root, i);
    }
}

//销毁二叉树
void destroy_tree(Node* root) {
    if (root == nullptr) {
        return;
    }

    destroy_tree(root->left);
    destroy_tree(root->right);

    delete root;
}

//前序遍历
void pre_order_recur(Node* head) {
    if (head == nullptr) {
        return;
    }
    std::cout << head->value << " ";
    pre_order_recur(head->left);
    pre_order_recur(head->right);
}

//中序遍历
void in_order_recur(Node* head) {
    if (head == nullptr) {
        return;
    }
    in_order_recur(head->left);
    std::cout << head->value << " ";
    in_order_recur(head->right);
}

//后序遍历
void post_order_recur(Node* head) {
    if (head == nullptr) {
        return;
    }
    post_order_recur(head->left);
    post_order_recur(head->right);
    std::cout << head->value << " ";
}

int main(void)
{
    Node* root = new Node();
    create_tree(root, 5, 9);

    pre_order_recur(root);
    std::cout << std::endl;
    in_order_recur(root);
    std::cout << std::endl;
    post_order_recur(root);
    std::cout << std::endl;

    destroy_tree(root);
    return 0;
}

非递归方式

非递归遍历需要一个栈辅助,把节点按照顺序压入栈中。前序遍历和后序遍历在循环开始前都需要头结点先入队。

  • 前序遍历:弹出就打印,有右就压右,有左就压左
  • 中序遍历:根不为空左递归(压栈),根若为空右递归,右递归时再打印
  • 后序遍历:需要两个栈;弹出压入s2,有左就压左(s1),有右就压右(s1),最后才打印
  • 层序遍历:层序遍历,使用队列
    1.头结点入队
    2.头结点弹出打印
    3.左右子节点先后入队列
    4.按顺序弹出打印,并将子节点先后入队

代码

#include <iostream>
#include <stack>

//节点
struct Node {
    int value;
    Node* left;
    Node* right;

    Node(int v = 0): value(v), left(nullptr), right(nullptr) {}
};

//向二叉树插入元素
void insert_tree(Node* &root, int value) {
    if (nullptr == root) {
        root = new Node(value);
        return;
    }
    if (value < root->value) {
        insert_tree(root->left, value);
    } else if (value > root->value) {
        insert_tree(root->right, value);
    }
}

//生成二叉树
void create_tree(Node* root, int root_value, int size) {
    root->value = root_value++;
    for (int i = 0; i <= size; ++i) {
        insert_tree(root, i);
    }
}

//销毁二叉树
void destroy_tree(Node* root) {
    if (root == nullptr) {
        return;
    }

    destroy_tree(root->left);
    destroy_tree(root->right);

    delete root;
}

//前序遍历
void pre_order(Node* head) {
    if (head != nullptr) {
        std::stack<Node*> s;
        s.push(head);

        while (!s.empty()) {
            head = s.top();
            s.pop();
            std::cout << head->value << " ";
            if (head->right != nullptr) {
                s.push(head->right);
            }
            if (head->left != nullptr) {
                s.push(head->left);
            }
        }
    }
}

//中序遍历
void in_order(Node* head) {
    if (head != nullptr) {
        std::stack<Node*> s;
        while (!s.empty() || head != nullptr) {
            if (head != nullptr) {
                s.push(head);
                head = head->left;
            } else {
                head = s.top();
                s.pop();
                std::cout << head->value << " ";
                head = head->right;
            }
        }
    }
}

//后序遍历
void post_order(Node* head) {
    if (head != nullptr) {
        std::stack<Node*> s1;
        std::stack<Node*> s2;
        s1.push(head);

        while (!s1.empty()) {
            head = s1.top();
            s1.pop();
            s2.push(head);
            if (head->left != nullptr) {
                s1.push(head->left);
            }
            if (head->right != nullptr) {
                s1.push(head->right);
            }
        }

        while (!s2.empty()) {
            head = s2.top();
            std::cout << head->value << " ";
            s2.pop();
        }
    }
}

//层序遍历,使用队列
//1.头结点入队
//2.头结点弹出打印
//3.左右子节点先后入队列
//4.按顺序弹出打印,并将子节点先后入队
void level_order(Node* head) {
    std::queue<Node*> q;
    q.push(head);
    Node *node;
    while (!q.empty()) {
        node = q.front();
        std::cout << node->value << std::endl;
        q.pop();
        if (node->left != nullptr) {
            q.push(node->left);
        }
        if (node->right != nullptr) {
            q.push(node->right);
        }
    }
}

int main(void)
{
    Node* root = new Node();
    create_tree(root, 5, 9);

    pre_order(root);
    std::cout << std::endl;
    in_order(root);
    std::cout << std::endl;
    post_order(root);
    std::cout << std::endl;

    destroy_tree(root);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值