二叉树的性质和遍历代码实现

本文介绍了二叉树的基本概念,包括其定义、特性,如满二叉树和完全二叉树的定义。文章还探讨了二叉树的遍历方法,如前序、中序、后序和层次遍历,并提供了递归和非递归的C++代码实现。此外,提到了二叉搜索树和平衡二叉树(AVL树)的概念。
摘要由CSDN通过智能技术生成

1. 二叉树的定义

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分。二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点。

2. 二叉树的性质

  1. 在二叉树的第i层上最多有2 i-1 个节点 。(i>=1)
  2. 二叉树中如果深度为k,那么最多有2k-1个节点。(k>=1)
  3. .n0=n2+1  n0表示度数为0的节点 n2表示度数为2的节点。
  4. 完全二叉树中,具有n个节点的完全二叉树的深度为[log2n]+1,其中[log2n]+1是向下取整。
  5. 若对含 n 个结点的完全二叉树从上到下且从左至右进行 1 至 n 的编号,则对完全二叉树中任意一个编号为 i 的结点:

    (1) 若 i=1,则该结点是二叉树的根,无双亲, 否则,编号为 [i/2] 的结点为其双亲结点;  

    (2) 若 2i>n,则该结点无左孩子,  否则,编号为 2i 的结点为其左孩子结点;

    (3) 若 2i+1>n,则该结点无右孩子结点,  否则,编号为2i+1 的结点为其右孩子结点。 

3. 二叉树的遍历

3.1 前序遍历

1.首先访问根节点。

2.其次前序访问左子树。

3.最后前序访问右子树。

3.2 中序遍历

1.先中序遍历左子树。

2.然后是根结点。

3.然后中序遍历右子树。

3.3 后序遍历

1.后序遍历左子树。

2.后序遍历右子树。

3.然后访问根节点。

3.4 层次遍历

逐层从左到右访问二叉树结点。

4. 特殊二叉树

4.1 满二叉树

1.一棵树深度为k,2^k-1个节点的树是满二叉树。

2.所有内部节点都有两个子节点,最底一层是叶子节点。

3.如果一颗树深度为h,最大层数为k,且深度与最大层数相同,即k=h。

4.第k层的结点数是:2^(k-1)。

5.总结点数是:2^k-1 (2的k次方减一)。

6.总节点数一定是奇数。

7.树高:h=log2(n+1)。

4.2 完全二叉树

1.若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h 层所有的结点都连续集中在最左边,这就是完全二叉树。

2.深度为k的完全二叉树,至少有2(k-1)个节点,至多有2k-1个节点。

3.树高h=log2n+1。

4.满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树。

4.3 二叉搜索树

1.左子树上所有结点的值均小于等于它的根结点的值,右子树上所有结点的值均大于等于它的根结点的值。

2.优点:查找速度快,二叉查找树比普通树查找更快。

3.缺点:出现平衡问题。

4.4 平衡二叉树

1.平衡二叉树全称平衡二叉搜索树,也叫AVL树,是一种自平衡的树,从上面二叉搜索树升级过来的,重点是改进了平衡问题。

 2.AVL树也规定了左结点小于根节点,右结点大于根节点。并且还规定了左子树和右子树的高度差不得超过1,这样保证了它不会成为线性的链表。 

5. 二叉树建立及遍历代码设计

代码由自己设计,前中后序遍历代码代码分为递归和非递归两个版本,代码如下:

#include <iostream>
#include <algorithm>
#include <stack>
#include <vector>
#include <queue>

using namespace std;

struct Node {
    char data;
    Node *lchild, *rchild;

    Node() = default;

    explicit Node(char data) : data(data) {
        lchild = nullptr;
        rchild = nullptr;
    }

    Node(char data, Node *left, Node *right) : data(data), lchild(left), rchild(right) {}
};

using BiTree = Node *;

// 创建二叉树(递归,通过前序遍历创建)
void create(BiTree &node) {
    char ch;
    cin >> ch;
    if (ch == '#') node = nullptr;// '#' => null character
    else {
        node = new Node;
        node->data = ch;
        create(node->lchild); //递归
        create(node->rchild);
    }
}

// 递归:实现前序遍历 DLR
void preTraversal(BiTree root) {
    if (root == nullptr) return;
    cout << root->data << " ";
    preTraversal(root->lchild);
    preTraversal(root->rchild);
}

// 递归:实现中序遍历 LDR
void inTraversal(BiTree root) {
    if (root == nullptr) return;
    inTraversal(root->lchild);
    cout << root->data << " ";
    inTraversal(root->rchild);
}

// 递归:实现后序遍历 LRD
void postTraversal(BiTree root) {
    if (root == nullptr) return;
    postTraversal(root->lchild);
    postTraversal(root->rchild);
    cout << root->data << " ";
}

//非递归:实现二叉树的中序遍历
void InOrderTranversal(BiTree root) {
    BiTree cur = root;
    stack<BiTree> cs;
    while (cur || !cs.empty()) {
        if (cur != nullptr) {
            cs.push(cur);
            cur = cur->lchild;
        } else {
            cur = cs.top();
            cs.pop();
            cout << cur->data << " ";
            cur = cur->rchild;
        }
    }
}

// 非递归:实现二叉树的前序遍历
void PreOrderTranversal(BiTree root) {
    vector<char> result;
    stack<BiTree> st;
    if (root == nullptr) return;
    st.push(root);
    while (!st.empty()) {
        auto node = st.top();
        st.pop();
        result.push_back(node->data);
        if (node->rchild != nullptr)
            st.push(node->rchild);
        if (node->lchild != nullptr)
            st.push(node->lchild);
    }
    for (auto res: result) cout << res << " ";
}

// 非递归:实现二叉树的后序遍历
void PostOrderTranversal(BiTree root) {
    vector<char> result;
    stack<BiTree> st;
    if (root == nullptr) return;
    st.push(root);
    while (!st.empty()) {
        auto node = st.top();
        st.pop();
        result.push_back(node->data);
        if (node->lchild != nullptr)
            st.push(node->lchild);
        if (node->rchild != nullptr)
            st.push(node->rchild);
    }
    reverse(result.begin(), result.end());
    for (auto res: result) cout << res << " ";
}

// 层序遍历
void LevelorderTraversal(BiTree root) {
    if (root == nullptr) return;
    queue<BiTree> que;
    que.push(root);
    while (!que.empty()) {
        auto node = que.front();
        que.pop();
        cout << node->data << " ";;
        if (node->lchild != nullptr) que.push(node->lchild);
        if (node->rchild != nullptr) que.push(node->rchild);
    }
}

int main() {
    BiTree T;
    cout << "Please enter the data of the node, # stands for empty : "; //ABC#D##EF###GHI###J##
    create(T);
    cout << "Created successfully!" << endl;
    cout << " ===========Preorder traversal Test=========== " << endl;
    preTraversal(T);
    cout << endl;
    cout << " ===========Inorder traversal Test=========== " << endl;
    inTraversal(T);
    cout << endl;
    cout << " ===========Postorder traversal Test=========== " << endl;
    postTraversal(T);
    cout << endl;
    cout << " ************Preorder traversal Test************ " << endl;
    PreOrderTranversal(T);
    cout << endl;
    cout << " ************Inorder traversal Test************ " << endl;
    InOrderTranversal(T);
    cout << endl;
    cout << " ************Postorder traversal Test************ " << endl;
    PostOrderTranversal(T);
    cout << endl;
    cout << " ************Leverlorder traversal Test************ " << endl;
    LevelorderTraversal(T);
    cout << endl;
    return 0;
}

运行结果如下:

Please enter the data of the node, # stands for empty :ABC#D##EF###GHI###J##
 Created successfully!
 ===========Preorder traversal Test===========
A B C D E F G H I J
 ===========Inorder traversal Test===========
C D B F E A I H G J
 ===========Postorder traversal Test===========
D C F E B I H J G A
 ************Preorder traversal Test************
A B C D E F G H I J
 ************Inorder traversal Test************
C D B F E A I H G J
 ************Postorder traversal Test************
D C F E B I H J G A
 ************Leverlorder traversal Test************
A B G C E H J D F I

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值