先说一下下,本篇我总结的是树的存储结构和二叉树的构造与遍历代码。树的知识有点多,后期我学会了,再跟大家分享。
二叉树的存储结构
我认为用链表来表达存储结构,可表达结点之间的逻辑关系。
其结点里面需要有左右结点和存放的数据。
template <typename DataType>
struct Node{
DataType data;
Node<DataType> *lchild,*rchild;
};
如图所示:
二叉树链表的遍历
二叉树的操作需要采用递归函数实现,对于遍历方式,一般有四种方法:
二叉树的遍历是指从根结点出发,按照某种次序访问①二叉树中的所有结点,使得每个结点被访问一次且仅被访问一次。二叉树由根结点(D),根结点的左子树(L)和根结点的右子树(R)三部分组成。 这三部分共有六种全排列,分别是DLR,LDR,LRD、DRL、RDL和RLD,不失一般性,约定先左子树后右子树,则有前序(根)遍历、中序(根)遍历和后序(根)遍历。如果按二又树的层序依次访问各结点,可得到另一种遍历次序:层序遍历。
前序遍历二叉树的操作定义为:若二叉树为空,则空操作返回:否则执行下述操作。 ①访间根结点; ②前序遍历根结点的左子树; ③前序遍历根结点的右子树。
template <typename DataType>
void BiTree<DataType>::PreOrder(BiNode<DataType>*bt){
if(bt==NULL){
return;
}else{
cout<<bt->data<<"\t";
PreOrder(bt->lchild);
PreOrder(bt->rchild);
}
}
中序遍历二叉树的操作定义为:若二叉树为空,则空操作返回:否则执行下述操作。 ①中序遍历根结点的左子树: ②访问根结点; ③中序遍历根结点的右子树。
template <typename DataType>
void BiTree<DataType>::InOrder(BiNode<DataType>*bt){
if(bt==NULL){
return;
}else{
InOrder(bt->lchild);
cout<<bt->data<<"\t";
InOrder(bt->rchild);
}
}
后序遍历二叉树的操作定义为:若二叉树为空,则空操作返回:否则执行下述操作。 ①后序遍历根结点的左子树: ②后序遍历根结点的右子树: ③访问根结点。
template <typename DataType>
void BiTree<DataType>::PosOrder(BiNode<DataType>*bt){
if(bt==NULL){
return;
}else{
PosOrder(bt->lchild);
PosOrder(bt->rchild);
cout<<bt->data<<"\t";
}
}
层序遍历二叉树的操作定义为:从二叉树的根结点开始,从上至下逐层遍历,同一层 按从左到右的顺序对结点逐个访问。
template <typename DataType>
void BiTree<DataType>::LevelOrder(){
Node<DataType>*Q[1000],*q = NULL;
int front = -1,rear = -1;
if(root = NULL){
return;
}
Q[++rear] = root;
while(front != rear){
q = Q[++front];
cout<<q->data<<"\t";
if(q->lchild != NULL){
Q[++rear] = q->lchild;
}
if(q->rchild != NULL){
Q[++rear] = q->rchild;
}
}
}
二叉树的构建与销毁
构造函数
本方法是通过根据一个结点序列来建立二叉树。需要把虚节点设置一个特定的值,比如用‘#’。
template <typename DataType>
Node<DataType> *BiTree<DataType>::Creat(){
Node<DataType> *bt;
char ch;
cin>>ch;
if(ch == '#'){
bt = NULL;
} else{
bt = new Node<DataType>;
bt->data = ch;
bt->lchild = Creat();
bt->rchild = Creat();
}
return bt;
}
析构函数
template <typename DataType>
void BiTree<DataType>::Release(Node<DataType> *bt){
if(bt = NULL){
return;
}else{
Release(bt->lchild);
Release(bt->rchild);
delete bt;
}
}
二叉树的使用
#include<iostream>
using namespace std;
struct BiNode
{
char data;
BiNode *lchild, *rchild;
};
class BiTree
{
public:
BiTree( ){root = Creat(root);} //构造函数,建立一棵二叉树
~BiTree( ){Release(root);} //析构函数,释放各结点的存储空间
void PreOrder( ){PreOrder(root);} //前序遍历二叉树
void InOrder( ){InOrder(root);} //中序遍历二叉树
void PostOrder( ){PostOrder(root);} //后序遍历二叉树
void LeverOrder( ); //层序遍历二叉树
private:
BiNode *Creat(BiNode *bt); //构造函数调用
void Release(BiNode *bt); //析构函数调用
void PreOrder(BiNode *bt); //前序遍历函数调用
void InOrder(BiNode *bt); //中序遍历函数调用
void PostOrder(BiNode *bt); //后序遍历函数调用
BiNode *root; //指向根结点的头指针
};
void BiTree :: PreOrder(BiNode *bt)
{
if (bt == NULL) return; //递归调用的结束条件
else {
cout << bt->data; //访问根结点bt的数据域
PreOrder(bt->lchild); //前序递归遍历bt的左子树
PreOrder(bt->rchild); //前序递归遍历bt的右子树
}
}
void BiTree :: InOrder(BiNode *bt)
{
if (bt == NULL) return; //递归调用的结束条件
else {
InOrder(bt->lchild); //前序递归遍历bt的左子树
cout << bt->data; //访问根结点bt的数据域
InOrder(bt->rchild); //前序递归遍历bt的右子树
}
}
void BiTree :: PostOrder(BiNode *bt)
{
if (bt == NULL) return; //递归调用的结束条件
else {
PostOrder(bt->lchild); //前序递归遍历bt的左子树
PostOrder(bt->rchild); //前序递归遍历bt的右子树
cout << bt->data; //访问根结点bt的数据域
}
}
void BiTree :: LeverOrder( )
{
BiNode *Q[100], *q = NULL; //顺序队列最多100个结点
int front = -1, rear = -1; //队列初始化
if (root == NULL) return; //二叉树为空,算法结束
Q[++rear] = root; //根指针入队
while (front != rear) //当队列非空时
{
q = Q[++front]; //出队
cout << q->data;
if (q->lchild != NULL) Q[++rear] = q->lchild;
if (q->rchild != NULL) Q[++rear] = q->rchild;
}
}
BiNode *BiTree :: Creat(BiNode *bt)
{
char ch;
cout << "请输入扩展二叉树的前序遍历序列,每次输入一个字符:";
cin >> ch; //输入结点的数据信息,假设为字符
if (ch == '#') bt = NULL; //建立一棵空树
else {
bt = new BiNode; bt->data = ch;
bt->lchild = Creat(bt->lchild); //递归建立左子树
bt->rchild = Creat(bt->rchild); //递归建立右子树
}
return bt;
}
void BiTree :: Release(BiNode *bt)
{
if (bt == NULL) return;
else{
Release(bt->lchild); //释放左子树
Release(bt->rchild); //释放右子树
delete bt; //释放根结点
}
}
int main( )
{
BiTree T; //定义对象变量T
cout << "该二叉树的前序遍历序列是:";
T.PreOrder( );
cout << "\n该二叉树的中序遍历序列是:";
T.InOrder( );
cout << "\n该二叉树的后序遍历序列是:";
T.PostOrder( );
cout << "\n该二叉树的层序遍历序列是:";
T.LeverOrder( );
return 0;
}
代码运行如下:
本次介绍就结束了,这次我介绍的结点使用的有两个指针,如果再加入一个,用来存储双亲结点,形成三叉链表。这样有利于寻找双亲结点。如这次分享对你有些收获,也给我一个赞支持与鼓励。
如你还想继续学下去,你可以看这篇,我在网上总结的知识点,可能有点长:
树的知识点总结https://blog.csdn.net/m0_67500944/article/details/126973302