二叉树操作实现
作者:互联网
二叉树操作实现
什么是二叉树?
树是常用的一种非线性数据结构。
树有很多衍生分类,其中,二叉树便是最为常见的一种。
二叉树的定义是以递归形式给出的:一棵二叉树是结点的一个有限集合,该集合可能为空,或则是由一个根节点加上两棵分别称为左子树、右子树的、互不相交的二叉树组成。
二叉树的特点是每个结点最多有两个子女,分别称为该节点的左子树和右子树。
在二叉树中不存在度大于2的结点,并且二叉树的字子树有左子树、右子树之分,其子树的次序不能颠倒。
二叉树是分支数最大不超过2的有根有序树。
二叉树的性质
二叉树的基本操作?
二叉树的基本操作有:
- 创建二叉树
- 前序遍历
- 中序遍历
- 后序遍历
- 层序遍历
- 求结点个数
- 求二叉树的深度
- 销毁二叉树
- 前/中/后序遍历的非递归实现
- 求叶子结点个数
- 求某结点的双亲结点
- 删除某节点的子树
二叉树相关算法的基本模式
由于树本身的定义就是递归定义的,
所以二叉树的基本操作多半基于递归思想实现。
二叉树结点结构体的设计
//结点结构体的定义
struct BiNode
{
/* data */
int data;
BiNode *lchild; //左孩子
BiNode *rchild; //右孩子
};
二叉树类的设计
我在设计类的时候,将涉及到对于结点root进行操作的递归调用过程的权限置为了private,并在public权限下设计了对外接口,这样做的目的是避免外界直接对根节点进行操作,是一种保护行为。
本质是函数重载和递归思想的实现。
class BiTree
{
private:
/* data */
int IsRoot=0;
BiNode *Creat(); //构造函数调用
void Release(BiNode *bt); //析构函数调用
void PreOrder(BiNode *bt); //前序遍历函数调用
void InOrder(BiNode *bt); //中序遍历函数调用
void PostOrder(BiNode *bt); //后序遍历函数调用过程
int Size(BiNode *bt); //获取结点个数调用过程
int Leaf(BiNode *bt); //求叶子结点个数的调用过程
void Parent(BiNode *bt); //求双亲结点调用过程
int Height(BiNode *bt); //获取二叉树高度的调用过程
int DelX(BiNode *bt,int x,int flag); //删除子树的递归调用过程
BiNode *root; //指向根节点的头指针
int target;
public:
//BiNode *root;
BiTree(){this->root=Creat();} //构造函数 建立一棵二叉树
~BiTree(){Release(root);} //析构函数,释放各结点的存储空间
void PreOrder(){PreOrder(root);} //前序遍历二叉树
void InOrder(){InOrder(root);} //中序遍历二叉树
void PostOrder(){PostOrder(root);} //后序遍历二叉树
int Size(){return Size(root);} //获取二叉树结点个数
int Leaf(){return Leaf(root);} //获取二叉树中叶子结点个数
int Height(){return Height(root);} //获取二叉树的高度(深度)
void PreOrderN(); //前序遍历算法非递归实现
void InOrderN(); //中序遍历算法非递归实现
void Parent(int x); //寻找双亲结点
void DelX(int x,int flag){DelX(root,x,flag);} //删除值为x的结点的子树
void LevelOrder(); //层序遍历
};
二叉树类的各算法实现
创建二叉树
创建时需要自己指定规则
BiNode *BiTree::Creat()
{
//可以采用广义表的方法去建立二叉树
// if(IsRoot==0)
// {
// cout<<"请输入根结点数据域(0表示空)"
// }
BiNode *bt;
int da; //临时变量
cout << "请输入该结点数据域(0表示空):";
cin >> da;
if (da == 0)
{
bt = nullptr;
}
else
{
bt = new BiNode;
bt->data = da;
bt->lchild = Creat(); //递归调用创建结点方法
bt->rchild = Creat(); //递归调用创建结点方法
}
return bt; //返回总树及每一棵子树的根节点root
}
销毁二叉树
销毁二叉树实际是后序遍历的一种操作
void BiTree::Release(BiNode *bt)
{
//析构函数的调用过程
cout << "析构" << endl;
//和后续遍历的思想一致
//左子树 右子树 根节点
//递归终止条件
if (bt == nullptr)
{
return;
}
else
{
Release(bt->lchild); //递归调用释放左子树
Release(bt->rchild); //递归调用释放右子树
delete bt;
}
cout << "析构成功" << endl;
}
前序遍历(递归)
前/中/后序遍历的递归算法基本一致,在此只对前序遍历进行说明。
void BiTree::PreOrder(BiNode *bt)
{
//递归调用的终止条件
if (bt == nullptr)
{
return;
}
else
{
//前序遍历: 根节点 左子树 右子树
cout << bt->data << " "; //输出数据域
PreOrder(bt->lchild);
PreOrder(bt->rchild);
}
}
求二叉树的总结点个数
递归
int BiTree::Size(BiNode *bt)
{
if (bt == nullptr)
{
return 0;
}
return 1 + Size(bt->lchild) + Size(bt->rchild);
}
求叶子结点个数
递归
int BiTree::Leaf(BiNode *bt)
{
//递归实现
if (bt == nullptr)
{
return 0;
}
if (bt->lchild == nullptr && bt->rchild == nullptr)
{
return 1;
}
return Leaf(bt->lchild) + Leaf(bt->rchild); //递归调用子函数,求子树中叶子结点的个数
}
求二叉树的深度
int BiTree::Height(BiNode *bt)
{
//求二叉树的高度(深度)
if (bt == nullptr)
{
return 0;
}
int i = Height(bt->lchild);
int j = Height(bt->rchild);
return i < j ? j + 1 : i + 1;
}
前序遍历非递归实现
基于顺序栈
void BiTree::PreOrderN()
{
//前序遍历算法的非递归实现
BiNode *bt = this->root;
BiNode *S[100]; //顺序栈 直接基于数组实现
int top = -1; //顺序栈初始化
while (bt != nullptr || top != -1)
{
//终止条件:是空树且栈为空栈
while (bt != nullptr)
{
cout << bt->data << " ";
S[++top] = bt; //根指针入栈
bt = bt->lchild;
}
if (top != -1)
{
bt = S[top--];
bt = bt->rchild;
}
}
}
求某结点的双亲
void BiTree::Parent(int x)
{
//int重载
this->target = x; //更改靶子的值
Parent(root); //开始寻找双亲
}
void BiTree::Parent(BiNode *bt)
{
if (bt != nullptr)
{
if (bt->lchild != nullptr && bt->lchild->data == target)
{
cout << "值为" << target << "的结点的双亲结点的值为" << bt->data << endl;
return;
}
if (bt->rchild != nullptr && bt->rchild->data == target)
{
cout << "值为" << target << "的结点的双亲结点的值为" << bt->data << endl;
return;
}
else
{
Parent(bt->lchild);
Parent(bt->rchild);
}
}
}
删除以某结点为根的子树
int BiTree::DelX(BiNode *bt, int x, int flag)
{
//删除值为x的结点的子树 递归方法实现 flag为标志 用于记录并判断
if (bt == nullptr)
{
return 0;
}
else
{
if (bt->data == x) //如果当前结点的值为x,则更改标志,并将标志向下传递
{
flag = 1;
}
int leftFlag = DelX(bt->lchild, x, flag); //递归左子树
int rightFlag = DelX(bt->rchild, x, flag); //递归右子树
if (1 == flag) //若flag为1,则说明其先祖结点有值为x,该子结点需要被删除
{
if (bt->data == x) //若其数据域为x,则应向上传递标志为1,以便赋空
{
return 1;
}
delete bt;
}
else
{
if (1 == leftFlag)
{
bt->lchild = nullptr; //从子结点接受收的信息,即如果其子结点为x,需要将其指针域赋空
}
if (1 == rightFlag)
{
bt->rchild == nullptr; //从子结点接受收的信息,即如果其子结点为x,需要将其指针域赋空
}
}
}
return 0;
}
层序遍历
基于队列
void BiTree::LevelOrder()
{
//层序遍历 基于队列
BiNode *Q[100]; //所需队列
BiNode *q = nullptr;
int front = -1, rear = -1; //队列初始条件
if (root == nullptr)
{
//空树不操作
return;
}
Q[++rear] = root; //根指针入队
while (front != rear)
{
//遍历条件:当队列非空时
q = Q[++front]; //出队
cout << q->data << " ";
if (q->lchild != nullptr)
Q[++rear] = q->lchild;
if (q->rchild != nullptr)
Q[++rear] = q->rchild;
}
}
源代码
BiTree.h
/*
二叉树
树结构本身是递归定义的
在这里,我们整个数据结构的定义和实现也大多基于递归
与欢行
*/
#include<iostream>
#include"queue"
using namespace std;
//结点结构体的定义
struct BiNode
{
/* data */
int data;
BiNode *lchild; //左孩子
BiNode *rchild; //右孩子
};
class BiTree
{
private:
/* data */
int IsRoot=0;
BiNode *Creat(); //构造函数调用
void Release(BiNode *bt); //析构函数调用
void PreOrder(BiNode *bt); //前序遍历函数调用
void InOrder(BiNode *bt); //中序遍历函数调用
void PostOrder(BiNode *bt); //后序遍历函数调用过程
int Size(BiNode *bt); //获取结点个数调用过程
int Leaf(BiNode *bt); //求叶子结点个数的调用过程
void Parent(BiNode *bt); //求双亲结点调用过程
int Height(BiNode *bt); //获取二叉树高度的调用过程
int DelX(BiNode *bt,int x,int flag); //删除子树的递归调用过程
BiNode *root; //指向根节点的头指针
int target;
public:
//BiNode *root;
BiTree(){this->root=Creat();} //构造函数 建立一棵二叉树
~BiTree(){Release(root);} //析构函数,释放各结点的存储空间
void PreOrder(){PreOrder(root);} //前序遍历二叉树
void InOrder(){InOrder(root);} //中序遍历二叉树
void PostOrder(){PostOrder(root);} //后序遍历二叉树
int Size(){return Size(root);} //获取二叉树结点个数
int Leaf(){return Leaf(root);} //获取二叉树中叶子结点个数
int Height(){return Height(root);} //获取二叉树的高度(深度)
void PreOrderN(); //前序遍历算法非递归实现
void InOrderN(); //中序遍历算法非递归实现
void Parent(int x); //寻找双亲结点
void DelX(int x,int flag){DelX(root,x,flag);} //删除值为x的结点的子树
void LevelOrder(); //层序遍历
};
BiTree.cpp
#include "BiTree.h"
BiNode *BiTree::Creat()
{
//可以采用广义表的方法去建立二叉树
// if(IsRoot==0)
// {
// cout<<"请输入根结点数据域(0表示空)"
// }
BiNode *bt;
int da; //临时变量
cout << "请输入该结点数据域(0表示空):";
cin >> da;
if (da == 0)
{
bt = nullptr;
}
else
{
bt = new BiNode;
bt->data = da;
bt->lchild = Creat(); //递归调用创建结点方法
bt->rchild = Creat(); //递归调用创建结点方法
}
return bt; //返回总树及每一棵子树的根节点root
}
void BiTree::Release(BiNode *bt)
{
//析构函数的调用过程
cout << "析构" << endl;
//和后续遍历的思想一致
//左子树 右子树 根节点
//递归终止条件
if (bt == nullptr)
{
return;
}
else
{
Release(bt->lchild); //递归调用释放左子树
Release(bt->rchild); //递归调用释放右子树
delete bt;
}
cout << "析构成功" << endl;
}
void BiTree::PreOrder(BiNode *bt)
{
//递归调用的终止条件
if (bt == nullptr)
{
return;
}
else
{
//前序遍历: 根节点 左子树 右子树
cout << bt->data << " "; //输出数据域
PreOrder(bt->lchild);
PreOrder(bt->rchild);
}
}
void BiTree::InOrder(BiNode *bt)
{
//中序遍历
if (bt == nullptr)
{
return;
}
else
{
//中序遍历: 左子树 根节点 右子树
InOrder(bt->lchild);
cout << bt->data << " ";
InOrder(bt->rchild);
}
}
void BiTree::PostOrder(BiNode *bt)
{
//后序遍历
if (bt == nullptr)
{
return;
}
else
{
//后序遍历:左子树 右子树 根节点
PostOrder(bt->lchild);
PostOrder(bt->rchild);
cout << bt->data << " ";
}
}
int BiTree::Size(BiNode *bt)
{
if (bt == nullptr)
{
return 0;
}
return 1 + Size(bt->lchild) + Size(bt->rchild);
}
int BiTree::Leaf(BiNode *bt)
{
//递归实现
if (bt == nullptr)
{
return 0;
}
if (bt->lchild == nullptr && bt->rchild == nullptr)
{
return 1;
}
return Leaf(bt->lchild) + Leaf(bt->rchild); //递归调用子函数,求子树中叶子结点的个数
}
int BiTree::Height(BiNode *bt)
{
//求二叉树的高度(深度)
if (bt == nullptr)
{
return 0;
}
int i = Height(bt->lchild);
int j = Height(bt->rchild);
return i < j ? j + 1 : i + 1;
}
void BiTree::PreOrderN()
{
//前序遍历算法的非递归实现
BiNode *bt = this->root;
BiNode *S[100]; //顺序栈 直接基于数组实现
int top = -1; //顺序栈初始化
while (bt != nullptr || top != -1)
{
//终止条件:是空树且栈为空栈
while (bt != nullptr)
{
cout << bt->data << " ";
S[++top] = bt; //根指针入栈
bt = bt->lchild;
}
if (top != -1)
{
bt = S[top--];
bt = bt->rchild;
}
}
}
void BiTree::InOrderN()
{
//中序遍历算法的非递归实现
BiNode *bt = this->root;
BiNode *S[100]; //顺序栈 直接基于数组实现
int top = -1; //顺序栈初始化
while (bt != nullptr || top != -1)
{
//终止条件:是空树且栈为空栈
while (bt != nullptr)
{
S[++top] = bt; //根指针入栈
bt = bt->lchild;
}
if (top != -1)
{
bt = S[top--];
cout << bt->data << " ";
bt = bt->rchild;
}
}
}
void BiTree::Parent(int x)
{
//int重载
this->target = x; //更改靶子的值
Parent(root); //开始寻找双亲
}
void BiTree::Parent(BiNode *bt)
{
if (bt != nullptr)
{
if (bt->lchild != nullptr && bt->lchild->data == target)
{
cout << "值为" << target << "的结点的双亲结点的值为" << bt->data << endl;
return;
}
if (bt->rchild != nullptr && bt->rchild->data == target)
{
cout << "值为" << target << "的结点的双亲结点的值为" << bt->data << endl;
return;
}
else
{
Parent(bt->lchild);
Parent(bt->rchild);
}
}
}
int BiTree::DelX(BiNode *bt, int x, int flag)
{
//删除值为x的结点的子树 递归方法实现 flag为标志 用于记录并判断
if (bt == nullptr)
{
return 0;
}
else
{
if (bt->data == x) //如果当前结点的值为x,则更改标志,并将标志向下传递
{
flag = 1;
}
int leftFlag = DelX(bt->lchild, x, flag); //递归左子树
int rightFlag = DelX(bt->rchild, x, flag); //递归右子树
if (1 == flag) //若flag为1,则说明其先祖结点有值为x,该子结点需要被删除
{
if (bt->data == x) //若其数据域为x,则应向上传递标志为1,以便赋空
{
return 1;
}
delete bt;
}
else
{
if (1 == leftFlag)
{
bt->lchild = nullptr; //从子结点接受收的信息,即如果其子结点为x,需要将其指针域赋空
}
if (1 == rightFlag)
{
bt->rchild == nullptr; //从子结点接受收的信息,即如果其子结点为x,需要将其指针域赋空
}
}
}
return 0;
}
void BiTree::LevelOrder()
{
//层序遍历 基于队列
BiNode *Q[100]; //所需队列
BiNode *q = nullptr;
int front = -1, rear = -1; //队列初始条件
if (root == nullptr)
{
//空树不操作
return;
}
Q[++rear] = root; //根指针入队
while (front != rear)
{
//遍历条件:当队列非空时
q = Q[++front]; //出队
cout << q->data << " ";
if (q->lchild != nullptr)
Q[++rear] = q->lchild;
if (q->rchild != nullptr)
Q[++rear] = q->rchild;
}
}
main.cpp
#include<iostream>
#include"BiTree.h"
using namespace std;
int main()
{
cout<<"基于链式存储结构的二叉树"<<endl;
BiTree b1;
cout<<"前序遍历(递归):";
b1.PreOrder();
cout<<endl;
cout<<"前序遍历(非递归):";
b1.PreOrderN();
cout<<endl;
cout<<"中序遍历(递归):";
b1.InOrder();
cout<<endl;
cout<<"中序遍历(非递归):";
b1.InOrderN();
cout<<endl;
cout<<"后序遍历:";
b1.PostOrder();
cout<<endl;
cout<<"层序遍历:";
b1.LevelOrder();
cout<<endl;
int fl=0;
b1.DelX(2,fl);
cout<<"前序遍历(递归):";
b1.PreOrder();
cout<<endl;
b1.Parent(4);
cout<<"当前二叉树共有"<<b1.Leaf()<<"个叶子结点"<<endl;
cout<<"当前二叉树共有"<<b1.Size()<<"个结点"<<endl;
cout<<"当前二叉树的高度(深度)为"<<b1.Height()<<endl;
system("pause");
return 0;
}
测试
main.cpp
int main()
{
cout<<"基于链式存储结构的二叉树"<<endl;
BiTree b1;
cout<<"前序遍历(递归):";
b1.PreOrder();
cout<<endl;
cout<<"前序遍历(非递归):";
b1.PreOrderN();
cout<<endl;
cout<<"中序遍历(递归):";
b1.InOrder();
cout<<endl;
cout<<"中序遍历(非递归):";
b1.InOrderN();
cout<<endl;
cout<<"后序遍历:";
b1.PostOrder();
cout<<endl;
cout<<"层序遍历:";
b1.LevelOrder();
cout<<endl;
int fl=0;
b1.DelX(2,fl);
cout<<"前序遍历(递归):";
b1.PreOrder();
cout<<endl;
b1.Parent(4);
cout<<"当前二叉树共有"<<b1.Leaf()<<"个叶子结点"<<endl;
cout<<"当前二叉树共有"<<b1.Size()<<"个结点"<<endl;
cout<<"当前二叉树的高度(深度)为"<<b1.Height()<<endl;
system("pause");
return 0;
}
我们创建这样的一棵树
标签:BiNode,结点,实现,nullptr,bt,int,二叉树,操作 来源: https://blog.csdn.net/EASYGOING45/article/details/120981595