数据结构-二叉树

一、二叉树

1.概念

二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点 [1] 。

2.结构模型图

9213b07eca806538fa88f4329adda144ad3482b5

如上图为一个二叉树,父节点最多只能有两个子节点

二、常用函数

  1. 求节点个数
  2. 求树的高度
  3. 求根节点
  4. 求当前节点的左孩子
  5. 求当前节点的右孩子
  6. 查找当前节点
  7. 查找当前节点的父节点
  8. 将二叉树置空
  9. 两个二叉树是否相同的比较
  10. 复制一个二叉树
  11. 前序遍历
  12. 中序遍历
  13. 后序遍历
  14. 层次遍历
  15. 前序法构建二叉树

三、代码实现

binTree.h

/**
 * @Author: lwj
 * @Date: 2022-06-17 09:10:37
 * @Description:二叉树方法的实现(结点类型是结构体实现)
 * @FilePath: /Linux_C_C-plus-plus/数据结构与算法(C++)/数据结构/BinTree/binTree.h
 **/
#pragma once
#include <stack>
#include <queue>
#include <iostream>

template <typename Type> //为的是声明友元类,调用BinTreeNode<Type>的私有数据
class BinTree;

template <typename Type>
struct Node //二叉树结点,结构体
{
    friend class BinTree<Type>;

    Type data;                                                                //数据
    Node<Type> *leftChild, *rightChild;                                       //分别为左孩子和右孩子
    Node() : data(Type()), leftChild(nullptr), rightChild(nullptr) {}         //无参构造
    Node(Type value, Node<Type> *left = nullptr, Node<Type> *rigth = nullptr) //有参构造
    {
        data = value;
        leftChild = left;
        rightChild = rigth;
    }
    ~Node(){};
};
template <typename Type>
class BinTree //二叉树类
{
private:
    Node<Type> *root; //指向二叉树的根

    /以下为内部接口//
private: //以下为内部接口
    void clear(Node<Type> *t);
    int size(Node<Type> *t) const;
    int height(Node<Type> *t) const;
    int leafNum(Node<Type> *t) const;
    Node<Type> *findI(const Type &value, Node<Type> *t) const;      //查找当前节点
    Node<Type> *findParent(Node<Type> *child, Node<Type> *t) const; //查找当前节点的父节点
    Node<Type> *copy(Node<Type> *t) const;                          //复制一个二叉树
    bool equal(Node<Type> *t1, Node<Type> *t2) const;               //两个二叉树是否相同的比较
    void clear(Node<Type> *t);                                      //清空二叉树
    void preOrder(Node<Type> *t) const;                             //递归前序遍历
    void inOrder(Node<Type> *t) const;                              //递归中序遍历
    void postOrder(Node<Type> *t) const;                            //递归后序遍历
    void preOrderCreate(Type flag, Node<Type> *&t);                 //前序法创建二叉树

    //以下为外部接口
public:
    BinTree() : root(nullptr) {}
    ~BinTree() { clear(); }
    bool empty() const { return root == nullptr; } //判空
    void clear()                                   //清空
    {
        if (root)
            clear(root);
        root = nullptr;
    }
    int size() const { return size(root); }                                             //求结点个数
    int height() const { return height(root); }                                         //求二叉树高度
    int leafNum() const { return leafNum(root); }                                       //求二叉树叶子数
    Node<Type> *findRoot() const { return root; }                                       //求根节点
    Node<Type> *findLeft(Node<Type> *t) const { return t->leftChild; }                  //求当前节点的左孩子
    Node<Type> *findRight(Node<Type> *t) const { return t->rightChild; };               //求当前节点的右孩子
    Node<Type> *findI(const Type &value) const { return findI(value, root); }           //查找当前结点
    Node<Type> *findParent(Node<Type> *child) const { return findParent(child, root); } //查找当前节点的父节点
    Node<Type> *copy() const { return copy(root); };                                    //复制一个二叉树
    bool equal(Node<Type> *t) const { return equal(root, t); }                          //两个二叉树是否相同的比较
    void preOrderTraverse() const { preOrder(root); }                                   //前序遍历
    void inOrederTraverse() const { inOrder(root); }                                    //中序遍历
    void postOrderTraverse() const { postOrder(root); }                                 //后序遍历
    void preOrderCreate(Type flag) { preOrderCreate(flag, root); }                      //前序法创建二叉树
};

//以下为接口实现//
template <typename Type>
void BinTree<Type>::clear(Node<Type> *t) //清空二叉树
{
    if (t->leftChild)
    {
        clear(t->leftChild);
    } //利用递归完成释放空间的功能
    if (t->rightChild)
    {
        clear(t->rightChild);
    }
    delete t;
}

template <typename Type>
int BinTree<Type>::size(Node<Type> *t) const //返回返回结点个数
{
    if (t == nullptr)
    {
        return 0;
    }
    return 1 + size(t->leftChild) + size(t->rightChild);
}

template <typename Type>
int BinTree<Type>::height(Node<Type> *t) const //返回二叉树高度
{
    if (t == nullptr)
    {
        return 0;
    }
    else
    {
        int l = height(t->leftChild);
        int r = height(t->rightChild);
        return 1 + (l > r ? l : r);
    }
}

template <typename Type>
int BinTree<Type>::leafNum(Node<Type> *t) const //返回二叉树叶子数
{
    if (t == nullptr)
    {
        return 0;
    }
    else if (t->leftChild == nullptr && t->rightChild == nullptr) //根就是叶子的时候
    {
        return 1;
    }
    else
    {
        return leafNum(t->leftChild) + leafNum(t->rightChild);
    }
}
template <typename Type>
Node<Type> *BinTree<Type>::findParent(Node<Type> *child, Node<Type> *t) const //查找当前节点的父节点
{
    if (t == nullptr || child == nullptr || child == t)
    {
        return nullptr;
    }
    if (t->leftChild == child || t->rightChild)
    {
        return t;
    }
    Node<Type> *p = findParent(t->leftChild);
    if (p)
    {
        return p;
    }
    return findParent(t->rightChild);
}

template <typename Type>
Node<Type> *BinTree<Type>::findI(const Type &value, Node<Type> *t) const //查找当前节点
{
    if (t == nullptr)
        return nullptr;
    if (t->data == value)
        return t;
    Node<Type> *p = findI(value, t->leftChild);
    if (p)
        return p;
    return findI(value, t->rightChild);
}

template <typename Type>
Node<Type> *BinTree<Type>::copy(Node<Type> *t) const //复制一个二叉树
{
    if (!t)
    {
        return nullptr;
    }
    Node<Type> *copyT = new Node<Type>(t->data);
    copyT->leftChild = copy(t->leftChild);
    copyT->rightChild = copy(t->rightChild);
    return copyT;
}

template <typename Type>
void BinTree<Type>::preOrder(Node<Type> *t) const //递归前序遍历
{
    if (t)
    {
        std::cout << t->data << ' '; //前序是从根开始遍历,所以输出语句放在第一条
        preOrder(t->leftChild);
        preOrder(t->rightChild);
    }
}

template <typename Type>
bool BinTree<Type>::equal(Node<Type> *t1, Node<Type> *t2) const //两个二叉树是否相同的比较
{
    if (t1 == nullptr && t2 == nullptr)
    {
        return true;
    }
    if (t1 != nullptr && t2 != nullptr && t1->data == t2->data && equal(t1->leftChild, t2->leftChild) && equal(t1->rightChild, t2->rightChild))
    {
        return true;
    }
    else
    {
        return false;
    }
}

template <typename Type>
void BinTree<Type>::inOrder(Node<Type> *t) const //递归中序遍历
{
    if (t)
    {
        inOrder(t->leftChild);
        std::cout << t->data << ' ';
        inOrder(t->rightChild);
    }
}

template <typename Type>
void BinTree<Type>::postOrder(Node<Type> *t) const //递归后序遍历
{
    if (t)
    {
        postOrder(t->leftChild);
        postOrder(t->rightChild);
        std::cout << t->data << ' ';
    }
}

/*使用带外部节点‘*’,‘*’号不存储,用来把二叉树补成一个二叉树,
这样更好理解,还能避免二叉树的二义性,如 abd**eg***c*fh**i** 。*/
template <typename Type>
void BinTree<Type>::preOrderCreate(Type flag, Node<Type> *&t) //前序法创建二叉树
{
    Type value;        //键盘输入的值
    std::cin >> value; //输入
    if (value != flag)
    {
        t = new Node<Type>(value);
        preOrderCreate(flag, t->leftChild);
        preOrderCreate(flag, t->rightChild);
    }
}

main.cpp

/**
 * @Author: lwj
 * @Date: 2022-06-17 09:10:47
 * @Description:测试二叉树功能
 * @FilePath: /Linux_C_C-plus-plus/数据结构与算法(C++)/数据结构/BinTree/main.cpp
 **/

#include "binTree.h"
#include <iostream>
using namespace std;
void test01()
{
    //测试的二叉树先序为:abd**eg***c*fh**i**
    BinTree<char> t1;
    t1.preOrderCreate('*');
    cout << "二叉树结点个数为:" << t1.size() << endl;
    cout << "二叉树高度为:" << t1.height() << endl;
    cout << "二叉树叶子数为:" << t1.leafNum() << endl;
    Node<char> *iNode = t1.findI('c');
    cout << "iNode->data = " << iNode->data << endl;
    cout << "元素c的父结点:" << t1.findParent(iNode)->data << endl;
    cout << "前序遍历二叉树t1:";
    t1.preOrderTraverse();
    cout << "\n中序遍历二叉树t1:";
    t1.inOrederTraverse();
    cout << "\n后序遍历二叉树t1:";
    t1.postOrderTraverse();
    cout << endl;

    BinTree<char> t2;
    t2.preOrderCreate('*');
    bool p = t2.equal(t1.findRoot());
    if (p)
    {
        cout << "相同!" << endl;
    }
    else
    {
        cout << "不相同!" << endl;
    }
}

int main()
{
    test01();
    return 0;
}

四、总结

​二叉树是一种特殊的数,他有树形结构递归的性质特点,可以通过二叉树这种特殊的数存储数据。而二叉树的类型也有很多,比如线索二叉树、B二叉树和B+二叉树等等,同时它们也都有各自的特点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里狼~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值