数据结构与算法:二叉树基础

        本篇带来的是二叉树基础部分的内容。还有一种向下调整建堆的方法……待补充。 

#include <iostream>
#include <stack>
using namespace std;
// 结构体定义
template <class BTDataType>
struct BinaryTreeNode
{
    BTDataType _data;
    BinaryTreeNode *_left;
    BinaryTreeNode *_right;
    BinaryTreeNode(const BTDataType &data) : _data(data), _left(nullptr), _right(nullptr) {}
};
template <class BTDataType>
class BinaryTree
{
    typedef BinaryTreeNode<BTDataType> BTNode;

public:
    BinaryTree() : root(nullptr) {}
    void BinaryTreeCreate()
    {
        root = new BTNode(1);
        BTNode *_node2 = new BTNode(2);
        BTNode *_node3 = new BTNode(3);
        BTNode *_node4 = new BTNode(4);
        BTNode *_node5 = new BTNode(5);
        BTNode *_node6 = new BTNode(6);
        BTNode *_node7 = new BTNode(7);
        root->_left = _node2;
        root->_right = _node4;
        _node2->_right = _node3;
        _node4->_left = _node5;
        _node4->_right = _node6;
        _node5->_right = _node7;
        _node7->_right = new BTNode(8);
    }
    // 下面是函数接口(因为root对外界是不可见的,所以只能叠甲进行操作)
    // 树的递归遍历
    void preOrder()
    {
        BinaryTreePreOrder(root);
        cout << endl;
    }
    void inOrder()
    {
        BinaryTreeInOrder(root);
        cout << endl;
    }
    void postOrder()
    {
        BinaryTreePostOrder(root);
        cout << endl;
    }
    // 树的非递归遍历
    void preOrder(int)
    {
        // 根左右
        BTNode *_root = root;
        stack<BTNode*> s;
        while(_root||!s.empty())
        {
            if(_root)
            {
                s.push(_root);
                cout << _root->_data << "->";
                _root = _root->_left;
            }
            else
            {
                BTNode *temp = s.top();
                s.pop();
                _root = temp->_right;
            }
        }
        cout << endl;
    }
    void inOrder(int)
    {
        // 左根右
        BTNode *_root = root;
        stack<BTNode*> s;
        while (_root||!s.empty())
        {
            // 一路左下,直到寻找到左孩子为空的位置,把栈顶元素从栈中弹出,并且访问该元素
            if(_root)
            {
                s.push(_root);
                _root = _root->_left;
            }
            else
            {
                // 此时,让_root指针指向栈顶元素的右孩子,因为左边已经没有元素可以去访问了,然后重复完整操作。
                // 当右孩子为空的时候,说明这棵子树访问完毕,可以访问之前的节点了
                BTNode *temp = s.top();
                s.pop();
                cout << temp->_data << "->";
                _root = temp->_right;
            }
        }
        cout << endl;
    }
    void postOrder(int)
    {
        BTNode* _root=root;
        BTNode *_repeat = nullptr;
        stack<BTNode*> s;
        while(_root||!s.empty()) 
        {
            // 左右根
            if(_root)
            {
                s.push(_root);
                _root = _root->_left;
            }
            else
            {
                BTNode* temp=s.top();
                if(temp->_right&&temp->_right!=_repeat)
                {
                    _root = temp->_right;
                }
                else
                {
                    cout << temp->_data << "->";
                    _repeat = temp;
                    s.pop();
                    _root = nullptr;
                }
            }
        }
    }
    int getTreeSize()
    {
        return BinaryTreeSize(root);
    }
    int getLeafSize()
    {
        return BinaryTreeLeafSize(root);
    }
    int getLevelSize(int k)
    {
        return BinaryTreeLevelKSize(root, k);
    }
    int getBTNodes()
    {
        return countNodes(root);
    }
    bool isComplete()
    {
        return BinaryTreeComplete(root);
    }
    BTNode *BTNodeFind(BTDataType &x)
    {
        return BinaryTreeFind(root, x);
    }
    ~BinaryTree()
    {
        DestroyTree(root);
    }

protected:
    // 前序遍历
    void BinaryTreePreOrder(BTNode *root)
    {
        if (root == nullptr)
        {
            cout << "NULL->";
            return;
        }
        cout << root->_data << "->";
        BinaryTreePreOrder(root->_left);
        BinaryTreePreOrder(root->_right);
    }
    // 中序遍历
    void BinaryTreeInOrder(BTNode *root)
    {
        if (root == nullptr)
        {
            cout << "NULL->";
            return;
        }
        BinaryTreeInOrder(root->_left);
        cout << root->_data << "->";
        BinaryTreeInOrder(root->_right);
    }
    // 后序遍历
    void BinaryTreePostOrder(BTNode *root)
    {
        if (root == nullptr)
        {
            cout << "NULL->";
            return;
        }
        BinaryTreePostOrder(root->_left);
        BinaryTreePostOrder(root->_right);
        cout << root->_data << "->";
    }
    // 计算二叉树的最大高度
    int BinaryTreeSize(BTNode *root)
    {
        if (root == nullptr)
            return 0;
        int leftTreeHeight = BinaryTreeSize(root->_left);
        int rightTreeHeight = BinaryTreeSize(root->_right);
        return (leftTreeHeight > rightTreeHeight ? leftTreeHeight : rightTreeHeight)+1;
    }
    // 计算二叉树的叶子节点数
    int BinaryTreeLeafSize(BTNode *root)
    {
        // 根节点为空则返回0
        if (root == nullptr)
            return 0;
        // 若左右子树均为空,则为叶子节点
        if (root->_left == nullptr && root->_right == nullptr)
            return 1;
        // 本节点非叶子节点则递归计算本节点的左右子树的叶子节点数
        return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
    }
    // 计算第K层节点的个数
    // 因为传入的是根节点,所以可以把根节点层数视为反向的第K层,然后再递归计算,当k>1的时候说明该节点还不是我所需要求的层数的节点,当k=1的时候说明该节点为我需要的节点,就返回1,否则递归计算左右子树的节点个数
    int BinaryTreeLevelKSize(BTNode *root, int k)
    {
        if (root == nullptr)
        {
            return 0;
        }
        if (k == 1)
            return 1;
        return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right, k - 1);
    }
    // 获取二叉树的总结点个数
    int countNodes(BTNode *root)
    {
        if (!root)
            return 0;
        return 1 + countNodes(root->_left) + countNodes(root->_right);
    }
    // 判断完全二叉树的辅助函数
    bool isCompleteUtil(BTNode *root, int index, int numberNodes)
    {
        if (!root)
            return true;
        // 当前节点的索引大于了节点总数量则返回false
        if (index >= numberNodes)
            return false;
        // 思想的本质是数组(顺序存储)
        bool left = isCompleteUtil(root->_left, 2 * index + 1, numberNodes);
        bool right = isCompleteUtil(root->_right, 2 * index + 2, numberNodes);

        return left && right;
    }

    // 判断二叉树是否是完全二叉树
    bool BinaryTreeComplete(BTNode *root)
    {
        int numberNodes = countNodes(root);
        return isCompleteUtil(root, 0, numberNodes);
    }
    void DestroyTree(BTNode *root)
    {
        if (!root)
            return;

        DestroyTree(root->_left);
        DestroyTree(root->_right);
        delete root;
    }
    BTNode *BinaryTreeFind(BTNode *root, BTDataType &x)
    {
        if (root == nullptr)
        {
            return nullptr;
        }
        if (root->_data == x)
        {
            return root;
        }
        BTNode *leftTree = BinaryTreeFind(root->_left, x);
        BTNode *rightTree = BinaryTreeFind(root->_right, x);
        if (leftTree)
        {
            return leftTree;
        }
        return rightTree;
    }

    BTNode *root;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值