一、二叉树
1.概念
二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点 [1] 。
2.结构模型图
如上图为一个二叉树,父节点最多只能有两个子节点
二、常用函数
- 求节点个数
- 求树的高度
- 求根节点
- 求当前节点的左孩子
- 求当前节点的右孩子
- 查找当前节点
- 查找当前节点的父节点
- 将二叉树置空
- 两个二叉树是否相同的比较
- 复制一个二叉树
- 前序遍历
- 中序遍历
- 后序遍历
- 层次遍历
- 前序法构建二叉树
三、代码实现
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+二叉树等等,同时它们也都有各自的特点。