本实验设计为类外函数
二叉树的函数设计精髓是递归函数的调用,设计时函数的形参传入的是tree,实际上是传入了此树的根节点,因此“当前树的根节点”概念比较重要。在递归之后,替代形参的是以此根节点的左右孩子节点为根节点的左右子树,实现将树不断简化直到只有叶子。尤其注意在递归之后有些量的值不可以改变,下面会有所提及。
tips:
节点声明中:普通节点为node,将树连根视为整体用tree。
创建树的递归,可以理解为创建完当前根节点后,继续创建其左右子树。
计算高度函数中, 可以理解为不断计算的是其左右子树的树高,比较后获得最大值。直到只有子叶,然后递归累积即可。
中序遍历+求高度函数中,高度的求解实际上是层次数的求解,易得:层次数=总树高-此节点的树的高度+1得到层次数。注意此处的总树高需要提前求出作为形参,在函数中进行计算会随着递归改变总高度的值。
中序调前k个函数中,和先序不同的是调处于中间位置的根节点时还需要判断溢出是否过k,原因是防止count在遍历完左子后已经到k了。
计算总节点数中,空节点返回0,其他情况都是返回1(此节点)+左右子树的节点数目。
复制树函数,按照先序先复制当前节点(视为根节点),再复制以此节点为根的左右子树。
交换左右叶子函数中,当扫描判断到空指针,则按照前面的create函数,没有键入data,不可以交换其data域(使用->data),只可以交换其指针值。
//binary_tree_code_test
#include <iostream>
using namespace std;
typedef char elementtype;
typedef struct TreeNode {
char data;//数据域
TreeNode* Lchild;//左孩子
TreeNode* Rchild;//右孩子
}*Tree,TreeNode;
//1.树的创建(先序)
void CreateTree(Tree &T){
char x;cin>>x;
if(x=='*'){T=NULL;return;}
else{
T=new TreeNode;
T->data=x;
CreateTree(T->Lchild);
CreateTree(T->Rchild);
}
}
//2.计算高度
int TreeDepth(const Tree &T){
if(T==NULL)return 0;
else{
int i=TreeDepth(T->Lchild);
int j=TreeDepth(T->Rchild);
return i>j?i+1:j+1;
}
}
//3.先序遍历
void Pre_Traversal(const Tree &T){
if(T){
cout<<T->data<<" ";
Pre_Traversal(T->Lchild);
Pre_Traversal(T->Rchild);
}
}
//4.先序调前k个
void Pre_Traversal_k(const Tree &T,int k){
static int count=1;
if(T&&count<=k){
cout<<T->data<<" ";count++;
Pre_Traversal_k(T->Lchild,k);
Pre_Traversal_k(T->Rchild,k);
}
}
//5.中序遍历
void Ino_Traversal(const Tree &T){
if(T){
Ino_Traversal(T->Lchild);
cout<<T->data<<" ";
Ino_Traversal(T->Rchild);
}
}
//6.中序遍历+求高度
void Ino_Traversal_h(const Tree &T,int height){
if(T){
Ino_Traversal_h(T->Lchild,height);
cout<<T->data<<height-TreeDepth(T)+1<<" ";
Ino_Traversal_h(T->Rchild,height);
}
}
//7.中序调前k个
void Ino_Traversal_k(const Tree &T,int k){
static int count=1;
if(T&&count<=k){
Ino_Traversal_k(T->Lchild,k);
if(count<=k){cout<<T->data<<" ";count++;}
Ino_Traversal_k(T->Rchild,k);
}
}
//8.后序遍历
void Pos_Traversal(const Tree &T){
if(T){
Pos_Traversal(T->Lchild);
Pos_Traversal(T->Rchild);
cout<<T->data<<" ";
}
}
//9.后序调前k个
void Pos_Traversal_k(const Tree &T,int k){
static int count=1;;
if(T&&count<=k){
Pos_Traversal_k(T->Lchild,k);
Pos_Traversal_k(T->Rchild,k);
if(count<=k){cout<<T->data<<" ";count++;}
}
}
//10.二叉树求度(叶子个数)
int TreeDegree(const Tree &T){
int degree;
if(T->Lchild&&T->Rchild)degree=2;
else if((T->Lchild&&!T->Rchild)||(!T->Lchild&&T->Rchild))degree=1;
else if(!T->Lchild&&!T->Rchild)degree=0;
return degree;
}
//11.度为2的节点个数
int search_node1(const Tree &T){
static int count=0;
if(T){
if(TreeDegree(T)==2)count++;
search_node1(T->Lchild);
search_node1(T->Rchild);
}
return count;
}
//12.叶子节点(度为0)个数
int search_node2(const Tree &T){
static int count=0;
if(T){
if(TreeDegree(T)==0)count++;
search_node2(T->Lchild);
search_node2(T->Rchild);
}
return count;
}
//13.计算总节点数
int TreeNodeCount(const Tree &T){
if(T==NULL)return 0;
//else if(T->Lchild==NULL&&T->Rchild==NULL)return 1;
else return TreeNodeCount(T->Lchild)+TreeNodeCount(T->Rchild)+1;
}
//14.复制树
void copy(const Tree &T,Tree &T1){
if(T==NULL)T1=NULL;
else{
T1=T;
copy(T->Lchild,T1->Lchild);
copy(T->Rchild,T1->Rchild);
}
}
//15.交换左右叶子
void exchange(Tree &T){
if(T==NULL)return;
else{
TreeNode *T0=new TreeNode;
T0=T->Lchild;
T->Lchild=T->Rchild;
T->Rchild=T0;
exchange(T->Lchild);
exchange(T->Rchild);
}
}
//ABC*D**E*F**GH**I**
int main(){
//创建二叉树
cout<<"请按照先序输入一个二叉树,空指针用*表示:"<<endl;
Tree T;CreateTree(T);
//先序、中序、后续遍历
cout<<"先序序列为:";Pre_Traversal(T);cout<<endl;
cout<<"中序序列为:";Ino_Traversal(T);cout<<endl;
cout<<"后序序列为:";Pos_Traversal(T);cout<<endl;
//先序求前k个
cout<<"请输入需要输出的节点个数k:";int k;cin>>k;
cout<<"先序中前k个节点值为:";Pre_Traversal_k(T,k);cout<<endl;
//求高度
int height=TreeDepth(T);
cout<<"树的高度为:"<<height<<endl;
//求度为2个数、叶子个数
cout<<"度为2的节点数目为:"<<search_node1(T);cout<<endl;
cout<<"叶子节点数目为:"<<search_node2(T);cout<<endl;
//计算总节点数
cout<<"总节点数目为:"<<TreeNodeCount(T);cout<<endl;
//中序遍历以及层次数
cout<<"中序序列及各节点层次数为:";
Ino_Traversal_h(T,height);cout<<endl;
//将T复制给T1
Tree T1;copy(T,T1);
cout<<"由T复制而来的T1的先序序列为:";
Pre_Traversal(T1);cout<<endl;
//交换每个节点的左右孩子指针的值
exchange(T);
cout<<"交换后的二叉树先序序列为:";
Pre_Traversal(T);cout<<endl;
return 0;
}