一、基本二叉树
//1、 二叉树的基本操作(必做题)
//
//(1) 根据二叉树的前序遍历序列,构建二叉树;
//
//(2) 实现二叉树的层序遍历、前序遍历、中序遍历和后序遍历;
//
//(3) 求二叉树的深度;
//
//(4) 求二叉树中叶子节点数量;
//
//(5) 求二叉树第K层结点数量;
//
//(6) 在二叉树中查找值为x的结点,若找到则返回结点指针,找不到则返回NULL
include
include
using namespace std;
template
struct Node
{
DataType TreeData;
Nodeleft;
Noderight;
};
//void AddNode(int data)
//{
// BTNode *s=new BTNode;
// s->left=NULL;
// s->right=NULL;
// s->data=data;
//}
//也可以把创建头结点root封装在一个函数里,将创建的root地址传到私有变量root中,也具有安全性。
template
class MyTree
{
public:
MyTree(){root=Create();}
~MyTree(){Release(root);}
void PreOrder(){PreOrder(root);};//前序遍历
void InOrder(){InOrder(root);};//中序遍历
void PostOrder(){PostOrder(root);};//后序遍历
void LevelOrder();//层序遍历
int TreeLength(){TreeLength(root);};//求树的深度
int TreeLeaf(){TreeLeaf(root);};//树的叶子结点个数
int TreeKNum(int k){TreeKNum(root,k);}; //树第k层结点个数
Node FindX(DataType x){FindX(root,x);};
private:
NodeCreate();
void Release(Nodebt);
void PreOrder(Nodebt);
void InOrder(Nodebt);
void PostOrder(Nodebt);
int TreeLength(Noderoot);
int TreeLeaf(Noderoot) ;
int TreeKNum(Noderoot,int k) ;
Node FindX(Noderoot,DataType x);
Noderoot;
};
template
Node MyTree::Create()//根据二叉树的前序遍历序列,构建二叉树
{
Nodebt;
char ch;
cout<<"请输入数据:";
cin>>ch;
if(ch=='#')
{
bt=nullptr;
}
else
{
bt=new Node;
bt->TreeData=ch;
bt->left=Create();
bt->right=Create();
}
return bt;
}
template
void MyTree::Release(Node*bt)
{
if(bt==nullptr)
return;
else{
Release(bt->left);
Release(bt->right);
delete bt;
}
}
//前序遍历
template
void MyTree::PreOrder(Node*bt)
{
if(bt==nullptr)
return;
else{
cout<TreeData<<" ";
PreOrder(bt->left);
PreOrder(bt->right);
}
}
//中序遍历
template
void MyTree::InOrder(Node*bt)
{
if(bt==nullptr)
return;
else{
InOrder(bt->left); cout<<bt->TreeData<<" "; InOrder(bt->right); } }
//后序遍历
template
void MyTree::PostOrder(Node*bt)
{
if(bt==nullptr)
return;
else{
PostOrder(bt->left); PostOrder(bt->right); cout<<bt->TreeData<<" "; } }
//层序遍历
template
void MyTree::LevelOrder()
{
NodeQ[100],q=nullptr;
int front=-1,rear=-1;
if(root==nullptr)
return;
Q[++rear]=root;
while(front!=rear)
{
q=Q[++front];
cout<TreeData<<" ";
if(q->left!=nullptr)
Q[++rear]=q->left;
if(q->right!=nullptr)
Q[++rear]=q->right;
}
}
//求二叉树的深度
template
int MyTree::TreeLength(Node*root)
{
if (root==nullptr) return 0;
int maxleft=TreeLength(root->left);
int maxright=TreeLength(root->right);
return max(maxleft,maxright)+1;
}
//求二叉树中叶子节点数量
template
int MyTree::TreeLeaf(Node*root)
{
if(root==nullptr)
return 0;
else{
int count1=TreeLeaf(root->left); int count2=TreeLeaf(root->right); if(root->left==nullptr&&root->right==nullptr) { return count1+count2+1; } else return count1+count2; } }
//求二叉树第K层结点数量
template
int MyTree::TreeKNum(Node*root,int k)
{
if(root==NULL)
return 0;
if(k==1)
return 1;
int left=TreeKNum(root->left,k-1);
int right=TreeKNum(root->right,k-1);
return left+right; }
//在二叉树中查找值为x的结点,若找到则返回结点指针,找不到则返回NULL
template
Node MyTree::FindX(Noderoot,DataType x)
{
if(root==nullptr)
return nullptr;
if(root->TreeData==x)
return root;
Noderet1=FindX(root->left,x) ;
if(ret1)
return ret1;
Noderet2=FindX(root->right,x) ;
if(ret2)
return ret2;
return nullptr; }
int main()
{
MyTreeT;
cout<<"该二叉树的前序遍历序列是:";
T.PreOrder();
cout<<endl;
cout<<"该二叉树的中序遍历序列是:";
T.InOrder();
cout<<endl;
cout<<"该二叉树的后序遍历序列是:";
T.PostOrder();
cout<<endl;
cout<<"该二叉树的层序遍历序列是:";
T.LevelOrder();
cout<<endl;
cout<<"该二叉树的深度是:"<<T.TreeLength() <<endl;
cout<<"该二叉树的叶子数量是:"<<T.TreeLeaf()<<endl;
for(int i=0;i<T.TreeLength();i++) { cout<<"该二叉树第"<<i+1<<"层结点数量是:"<<T.TreeKNum(i+1)<<endl; } char x; cout<<"请输入你要查找的值:"; cin>>x; if(T.FindX(x)==nullptr) cout<<"没找到"; else cout<<"找到了,结点地址为:"<<T.FindX(x); return 0; }
伪代码说明:
//伪代码:
//定义模板结构体 Node,包含:
// 数据类型 TreeData
// 指向左子节点的指针 left
// 指向右子节点的指针 right
//
//定义模板类 MyTree,包含:
// 私有成员变量 root,类型为 Node
//
// 构造函数 MyTree():
// 调用 Create() 方法初始化 root
//
// 析构函数 ~MyTree():
// 调用 Release() 方法释放 root 及其子节点
//
// 成员函数:
// void PreOrder():前序遍历树,调用 PreOrder(root)
// void InOrder():中序遍历树,调用 InOrder(root)
// void PostOrder():后序遍历树,调用 PostOrder(root)
// void LevelOrder():层序遍历树
// {
// 使用一个队列来辅助遍历。
// 首先将根节点入队,然后进入一个循环,每次从队列中取出一个节点,输出其值,并将其左右子节点(如果存在)依次入队。循环直到队列为空。
// }
// int TreeLength():返回树的深度,调用 TreeLength(root)
// int TreeLeaf():返回树的叶子节点数量,调用 TreeLeaf(root)
// int TreeKNum(int k):返回树第 k 层节点数量,调用 TreeKNum(root, k)
// Node FindX(DataType x):查找值为 x 的节点,调用 FindX(root, x)
//
// 私有成员函数:
// Node Create():根据用户输入的前序遍历序列构建二叉树
// {
// 初始化MyTree对象,调用Create()函数创建一个空的或根据输入构建的二叉树,并将根节点指针root指向这个新创建的树。
// }
// void Release(Node bt):释放二叉树 bt 的所有节点
// {
// 释放MyTree对象所占用的内存资源,即递归地删除二叉树中的所有节点。
// }
// void PreOrder(Node bt):前序遍历二叉树 bt
// void InOrder(Node bt):中序遍历二叉树 bt
// void PostOrder(Node bt):后序遍历二叉树 bt
// int TreeLength(Node root):计算二叉树 root 的深度
// {
// 递归地计算左子树和右子树的深度,并返回较大值加1(加上当前节点)。
// }
// int TreeLeaf(Node root):计算二叉树 root 的叶子节点数量
// {
// 递归计算左子树和右子树中的叶子节点个数,
// 如果当前节点是叶子节点(即没有左右子节点),则计数加1。
// }
// int TreeKNum(Node root, int k):计算二叉树 root 第 k 层的节点数量
// {
// 递归计算左子树和右子树中第K-1层节点的个数之和(因为当前节点是第1层,所以要减1)。当K为1时,直接返回1(因为任何非空树的根节点都在第1层)。
// }
// Node FindX(Node root, DataType x):在二叉树 root 中查找值为 x 的节点
// {
// 递归地在左子树和右子树中查找,如果找到值为x的节点,则返回该节点的指针;如果左右子树都没有找到,则返回nullptr
// }
//
//主函数 main():
// 创建 MyTree 类型的对象 T
// 输出 T 的前序、中序、后序和层序遍历序列
// 输出 T 的深度和叶子节点数量
// 对于从 1 到树深度的每一层,输出该层的节点数量
// 提示用户输入要查找的值 x
// 调用 FindX(x) 查找值 x,输出查找结果
二、排序二叉树
//2、 二叉树的应用:二叉排序树(必做题)
//
//问题描述:二叉排序树,也称为二叉查找树。可以是一颗空树,也可以是一颗具有如下特性的非空二叉树: 1. 若左子树非空,则左子树上所有节点值均不大于根节点值;
//2. 若右子树非空,则右子树上所有节点值均不小于根节点值; 3. 左、右子树本身也是一颗二叉排序树。 现在给你N个值各不相同的节点。
//
//(1)构建二叉排序树,即按给定顺序将结点插入一个初始为空树的二叉排序树中。
//
//(2)输出二叉排序树的中序遍历序列。
//
//(3)根据二叉排序树的性质,实现二叉排序树的结点查找功能,即查找某个值为key的结点否在二叉排序树中,若找到则输出查找过程中结点比较次数,若找不到则输出“Not Found”。
//
//(4)对于相同的数据元素集合,请分析在数据元素顺序不同的情况下,构建的二叉排序树是否相同,对节点查找操作的性能有何影响。
include
include
using namespace std;
template
struct Node
{
DataType TreeData;
Nodeleft;
Noderight;
};
template
class MyTree
{
public:
MyTree(){root=nullptr;}
~MyTree(){Release(root);}
void InsertNode(DataType x);
void InOrder(){InOrder(root);};//中序遍历
int FindX(DataType x){FindX(root,x);};
private: void Release(Node<DataType>*bt); void InOrder(Node<DataType>*bt); int FindX(Node<DataType>*root,DataType x); Node<DataType>*root; };
template
void MyTree::Release(Node*bt)
{
if(bt==nullptr)
return;
else{
Release(bt->left);
Release(bt->right);
delete bt;
}
}
template
void MyTree::InsertNode(DataType x)
{
if(root==nullptr)
{
Node*newnode=new Node;
newnode->TreeData =x;
newnode->left=nullptr;
newnode->right=nullptr;
root=newnode;
return;
}
Node<DataType>*location=root; Node<DataType>*prev=nullptr; while(location!=nullptr) { prev=location; if(x<location->TreeData) { location=location->left; } else { location=location->right; } } if(x < prev->TreeData) { Node<DataType>*newnode=new Node<DataType>; newnode->TreeData =x; newnode->left=nullptr; newnode->right=nullptr; prev->left=newnode; } else { Node<DataType>*newnode=new Node<DataType>; newnode->TreeData =x; newnode->left=nullptr; newnode->right=nullptr; prev->right=newnode; } }
template
void MyTree::InOrder(Node*bt)
{
if(bt==nullptr)
return;
else
{
InOrder(bt->left );
cout<TreeData <<" ";
InOrder(bt->right );
}
}
template //只要用到递归都需要root形参
int MyTree::FindX(Node*root,DataType x)
{
int count=0;
while(x!=root->TreeData)
{
if(xTreeData)
{
root=root->left;
count++;
}
if(x>root->TreeData)
{
root=root->right;
count++;
}
}
if(root==nullptr) return 0; return count+1; }
int main()
{
MyTreeT;
T.InsertNode(5) ;
T.InsertNode(10) ;
T.InsertNode(6) ;
T.InsertNode(3) ;
T.InsertNode(15) ;
T.InsertNode(20) ;
T.InsertNode(11) ;
T.InOrder() ;
cout<<endl; int x; cout<<"请输入你要查找的值:"; cin>>x; if(T.FindX(x)==0) cout<<"Not Found"; else cout<<"找到了,查找比较次数为:"<<T.FindX(x); return 0; }
伪代码说明:
//伪代码:
//定义结构体 Node:
// 包含:
// 数据域 TreeData
// 指向左子节点的指针 left
// 指向右子节点的指针 right
//
//定义类 MyTree:
// 包含:
// 私有成员:
// 指向根节点的指针 root
//
// 公有成员:
// 构造函数 MyTree(),初始化 root 为 nullptr
// 析构函数 ~MyTree(),释放所有节点
// 插入节点的方法 InsertNode(数据类型 x)
// 中序遍历的方法 InOrder()
// 查找节点的方法 FindX(数据类型 x),返回查找过程中的比较次数,如果未找到则返回 0
//
//私有成员函数:
// 释放树的方法 Release(Node bt)
// 中序遍历的方法 InOrder(Node bt)
// 查找节点的方法 FindX(Node* root, 数据类型 x)
//
//
//实现 MyTree 的成员函数:
//
//释放树:
// 如果节点 bt 为空,则返回
// 否则:
// 递归释放左子树
// 递归释放右子树
// 删除当前节点
//
//插入节点:
// 如果根节点为空,则创建新节点并设为根节点
// 否则:
// 找到插入位置的前一个节点 prev
// 根据 x 的值决定插入到 prev 的左子树还是右子树
//
//中序遍历:
// 如果节点 bt 为空,则返回
// 否则:
// 递归中序遍历左子树
// 访问当前节点(输出 TreeData)
// 递归中序遍历右子树
//
//查找节点:
// 初始化计数器 count 为 0
// 在树中查找 x,比较 x 与当前节点的 TreeData:
// 如果 x 小于 TreeData,则移动到左子节点,count 加 1
// 如果 x 大于 TreeData,则移动到右子节点,count 加 1
// 如果找到 x,则返回 count + 1
// 如果未找到(即 root 为 nullptr),则返回 0
//
//主函数 main():
// 创建 MyTree 实例 T
// 向 T 中插入一系列节点(5, 10, 6, 3, 15, 20, 11)
// 对 T 进行中序遍历并输出结果
// 提示用户输入要查找的值 x
// 调用 FindX 方法查找 x
// 根据返回值输出查找结果(找到或未找到,以及比较次数)