数据结构实验5.二叉树的一些功能
1.实现的功能
(1)按先序遍历的方式输入二叉树
(2)二叉搜索树的方式插入节点
(3)前中后序遍历二叉树
(4)层序遍历二叉树
(5)普通搜索二叉树数据
(6)按搜索二叉树的方式搜索数据
(7)删除某个节点(若有两个孩子,左孩子插到原来的位置,将右孩子插到原左孩子的最近的度小于2的节点上,优先左孩子,所以用了之后就不能用6搜索了)。
(8)得到叶子的个数,可选是否输出叶子节点
(9)得到树的高度
(10)得到树的宽度
(11)输出所有从叶子到根的路径,可以容易的改成逆序。
(12)自定义结束符
2.依赖的头文件
“anotherQueue.h”
#ifndef __ANOTHERQUEUE_H__
#define __ANOTHERQUEUE_H__
template<typename T>
class Queue
{
public:
Queue()
{
maxsize = 10;
data = new T[maxsize];
head = tail = 0;
is_full = 0;
}
Queue(int n)
{
maxsize = n;
data = new T[maxsize];
head = tail = 0;
is_full = 0;//初始为否
}
void push(T d);
T pop();
T popStack();
T getHead(){return data[head];}
bool isEmpty(){return ((head == tail) && ! is_full);}
bool isFull(){return is_full;}
private:
T *data;
int head;
int tail;
bool is_full;
int maxsize;
};
template<typename T>
void Queue<T>::push(T d)
{
if(is_full) return;
data[tail] = d;
tail = (tail+1) % maxsize;
if(tail == head) is_full = 1;
}
template<typename T>
T Queue<T>::pop()
{
if(isEmpty()) return(T) 0;
T rslt = data[head];
head = (head+1) % maxsize;
return rslt;
}
template<typename T>
T Queue<T>::popStack()
{
if(isEmpty()) return(T) 0;
tail = (tail-1) % maxsize;
if(tail < 0)//归位
tail = maxsize - 1;
T rslt = data[tail];
return rslt;
}
#endif
3.本体
“BiTree.h”
#ifndef __BITREE_H__
#define __BITREE_H__
#define nullptr 0
#include<iostream>
#include"anotherQueue.h"
using namespace std;
template<typename T>
struct Node
{
Node()
{
data = 0;
lchild = rchild = nullptr;
}
Node(T d)
{
data = d;
lchild = rchild = nullptr;
}
T data;
Node<T> *lchild;
Node<T> *rchild;
};
template<typename T>
class BiTree
{
public:
BiTree()
{
cout<<"请输入结束符";
cin>>terminator;
create(root);
}
void addNode();
void preOrder(){preOrder(root);}
void inOrder(){inOrder(root);}
void postOrder(){postOrder(root);}
void queueLevelOrder(){queueLevelOrder(root);};
Node<T> *srchData(T srch_data){return srchData(root,srch_data);}
Node<T> *srchDataBST(T srch_data){return srchDataBST(root,srch_data);}
void delData(T del_data);
int getLeaveNum(int show_leave){return getLeaveNum(root,show_leave);}
int getTreeHight(){return getTreeHight(root);}
int getTreeWidth(){return getTreeWidth(root);}
void showLeaveToRootWay(){showLeaveToRootWay(root);}
private:
void srchTreeAddNode(Node<T> *&root,T d);
void create(Node<T> *&root);
void preOrder(Node<T> *root);
void inOrder(Node<T> *root);
void postOrder(Node<T> *root);
void levelOrder(Node<T> *root);
void queueLevelOrder(Node<T> *root);
Node<T> *srchData(Node<T> *root,T srch_data);
Node<T> *srchDataBST(Node<T> *root,T srch_data);
Node<T> *srchSingle(Node<T> *root);
int delData(Node<T> *&root,T del_data);
void insData(Node<T> *&root,T ins_data,int ins_pos);
int getLeaveNum(Node<T> *root,int show_leave);
int getTreeHight(Node<T> *root);
int getTreeWidth(Node<T> *root);
void showLeaveToRootWay(Node<T> *root);
Queue<Node<T>*> order_helper;
Node<T> *root;
T terminator;
};
template<typename T>
void BiTree<T>::addNode()
{
T d;
while(1)
{
cin>>d;
if(d == terminator)
break;
srchTreeAddNode(root,d);
}
}
template<typename T>
void BiTree<T>::delData(T del_data)
{
Node<T> *ptoroot = new Node<T>;//声明一个头节点左子树指针指向原树的根
ptoroot->lchild = root;
while(delData(ptoroot,del_data))
{
if(root)
ptoroot->lchild = root;
}
delete ptoroot;//释放头结点
}
template<typename T>
void BiTree<T>::srchTreeAddNode(Node<T> *&root,T d)
{
if(root == nullptr)
{//若无数据
root = new Node<T>(d);
return;
}
if(root->data > d)
{//大于
srchTreeAddNode(root->lchild,d);
return;
}
if(root->data == d)
{//等于
return;
}
if(root->data < d)
{//小于
srchTreeAddNode(root->rchild,d);
return;
}
}
template<typename T>
void BiTree<T>::create(Node<T> *&root)
{
T d;
cin>>d;
if(d == terminator)
{
root = nullptr;
return;
}
root = new Node<T>(d);
create(root->lchild);
create(root->rchild);
}
template<typename T>
void BiTree<T>::preOrder(Node<T> *root)
{
if(root == nullptr)
return;
cout<<root->data<<' ';
preOrder(root->lchild);
preOrder(root->rchild);
}
template<typename T>
void BiTree<T>::inOrder(Node<T> *root)
{
if(root == nullptr)
return;
inOrder(root->lchild);
cout<<root->data<<' ';
inOrder(root->rchild);
}
template<typename T>
void BiTree<T>::postOrder(Node<T> *root)
{
if(root == nullptr)
return;
postOrder(root->lchild);
postOrder(root->rchild);
cout<<root->data<<' ';
}
template<typename T>
void BiTree<T>::queueLevelOrder(Node<T> *root )
{
while(root)
{
cout<<root->data<<' ';
if(root->lchild)order_helper.push(root->lchild);
if(root->rchild)order_helper.push(root->rchild);
root = order_helper.pop();
}
}
template<typename T>
Node<T> *BiTree<T>::srchData(Node<T> *root,T srch_data)
{
Node<T> *pt;
if(root == nullptr)
return root;
if(root -> data == srch_data)
return root;
pt = srchData(root->lchild,srch_data);
if(pt)
return pt;
pt = srchData(root->rchild,srch_data);
if(pt)
return pt;
}
template<typename T>
Node<T> *BiTree<T>::srchDataBST(Node<T> *root,T srch_data)
{
Node<T> *pt;
cout<<1;
if(root == nullptr)
return root;
if(root->data < srch_data)
{
pt = srchDataBST(root->rchild,srch_data);
if(pt)
return pt;
}
if(root->data == srch_data)
{
return root;
}
if(root->data > srch_data)
{
pt = srchDataBST(root->lchild,srch_data);
if(pt)
return pt;
}
}
template<typename T>
Node<T> *BiTree<T>::srchSingle(Node<T> *root)
{
Node<T> *pt;
if(root-> lchild == NULL ||root -> rchild == NULL)
{
return root;
}
pt = srchSingle(root -> lchild);
if(pt)
return pt;
pt = srchSingle(root -> rchild);
if(pt)
return pt;
}
template<typename T>
int BiTree<T>::delData(Node<T> *&root,T del_data)
{//删除一个值为del_data 的节点,此处使用不传入双亲节点的方法
if(root == nullptr)
return 0;
if(root->lchild)
{//先看当前节点的的左孩子
if(root->lchild -> data == del_data)
{//查找到要删除的节点
if(!(root->lchild -> lchild) && !(root->lchild ->rchild))
{//若该节点是叶子节点
delete root->lchild;
if(root->lchild == this->root)//由于之前将原root视为辅助头结点的左子树,此处若删除的是树根,就把root重新赋值为
this->root = NULL;
root->lchild = NULL;
return 1;
}
if(root->lchild ->lchild && root->lchild ->rchild)
{//若该节点有两个孩子,将左孩子接到原位置,为右孩子找新父母,且新父母在当前树的子树下
Node<T> *pt = root -> lchild -> lchild;//暂存左孩子
Node<T> *new_parent = srchSingle(root->lchild);//找到不是两个孩子的父母,处理右节点 注:此处必把要删除的节点的右子树接到左子树最近的空枝上
if(new_parent->lchild)
{//若新父母有左孩子
new_parent->rchild = root -> lchild ->rchild;
}
else
{//没有左孩子
new_parent->lchild = root ->lchild ->rchild;
}
delete root -> lchild;//删掉左孩子
if(root->lchild == this->root)//由于之前将原root视为辅助头结点的左子树,此处若删除的是树根,就把root重新赋值为
this->root = pt;
root -> lchild = pt;//连接左孩子
return 1;
}
if(root->lchild ->lchild || root->lchild ->rchild)
{//若该节点有一个孩子,有两个孩子的情况在上面处理了,所以不会出现在这里
if(root->lchild ->lchild)
{//是左孩子
Node<T> *pt = root -> lchild ->lchild;
delete root -> lchild;
if(root->lchild == this->root)//由于之前将原root视为辅助头结点的左子树,此处若删除的是树根,就把root重新赋值为
this->root = pt;
root -> lchild = pt;//替换
return 1;
}
else
{//右孩子
Node<T> *pt = root -> lchild ->rchild;
delete root -> lchild;
root -> lchild = pt;//替换
return 1;
}
}
}
}
if(root->rchild)
{//再看当前节点的的右孩子
if(root->rchild->data == del_data)
{//查找到要删除的节点
if(!(root->rchild -> lchild) && !(root->rchild ->rchild))
{//若该节点是叶子节点
delete root->rchild;
root->rchild = NULL;
return 1;
}
if(root->rchild ->lchild && root->rchild ->rchild)
{//若该节点有两个孩子,将左孩子接到原位置,为右孩子找新父母,且新父母在当前树的子树下
Node<T> *pt = root -> rchild -> lchild;//暂存左孩子
Node<T> *new_parent = srchSingle(root->rchild);//找到不是两个孩子的父母,处理右节点
if(new_parent->lchild)
{//若新父母有左孩子
new_parent->rchild = root -> rchild ->rchild;
}
else
{//有右孩子
new_parent->lchild = root ->rchild ->rchild;
}
delete root -> rchild;//删掉右孩子
root -> rchild = pt;//连接右孩子
return 1;
}
if(root->rchild ->lchild || root->rchild ->rchild)
{//若该节点有一个孩子,有两个孩子的情况在上面处理了,所以不会出现在这里
if(root->rchild ->lchild)
{//是左孩子
Node<T> *pt = root -> rchild ->lchild;
delete root -> rchild;
root -> rchild = pt;//替换
return 1;
}
else
{//右孩子
Node<T> *pt = root -> rchild ->rchild;
delete root -> rchild;
root -> rchild = pt;//替换
return 1;
}
}
}
}
delData(root -> lchild,del_data);
delData(root -> rchild,del_data);
return 0;
}
template<typename T>
int BiTree<T>::getLeaveNum(Node<T> *root,int show_leave)
{
int num;
if(root == nullptr)
return 0;
if(root->lchild == nullptr && root->rchild == nullptr)
{
if(show_leave)
cout<<root->data<<' ';
return 1;
}
num = getLeaveNum(root->lchild,show_leave) + getLeaveNum(root->rchild,show_leave);
return num;
}
template<typename T>
int BiTree<T>::getTreeHight(Node<T> *root)
{
int l_hight,r_hight;
if(root == nullptr)
return 0;
if(root->lchild == nullptr &&root->rchild == nullptr)
return 1;
l_hight = getTreeHight(root->lchild);
r_hight = getTreeHight(root->rchild);
return ((l_hight>r_hight?l_hight:r_hight)+1);//算上自己的高度
}
template<typename T>
int BiTree<T>::getTreeWidth(Node<T> *root)
{
if(root == nullptr)
return 0;
int this_level_node_left = 1;//本层剩余的节点数
int max_width = this_level_node_left;
int next_level_node_count = 0;//下一层的节点数
order_helper.push(root);//首先入栈整棵树的根节点
while(!order_helper.isEmpty())
{
while(this_level_node_left)
{
root = order_helper.pop();
if(root->lchild)
{
order_helper.push(root->lchild);
next_level_node_count++;
}
if(root->rchild)
{
order_helper.push(root->rchild);
next_level_node_count++;
}
this_level_node_left--;
}
max_width = max_width > next_level_node_count?max_width:next_level_node_count;
this_level_node_left = next_level_node_count;
next_level_node_count = 0;
}
return max_width;
}
template<typename T>
void BiTree<T>::showLeaveToRootWay(Node<T> *root)
{
if(root == nullptr)//遍历结束
return;
if(root->lchild == nullptr && root->rchild == nullptr)
{//是叶子节点
order_helper.push(root);
int count = 0,i = 0;
Node<T> **printway = new Node<T>*[getTreeHight()];
while(!order_helper.isEmpty())
{//得到路径
printway[count++] = order_helper.popStack();
}
i = count-1;
while(i>=0)
{//再塞回去
order_helper.push(printway[i--]);
}
for(i = 0;i < count;i++)
{//输出路径
cout<<printway[i]->data<<' ';
}
cout<<endl;
order_helper.popStack();
return;
}
order_helper.push(root);
if(root->lchild)
{
showLeaveToRootWay(root->lchild);
}
if(root->rchild)
{
showLeaveToRootWay(root->rchild);
}
order_helper.popStack();
}
#endif
4. 一个简单的测试用代码
#include<iostream>
#include<conio.h>
#include"anotherQueue.h"
#include"BiTree.h"
#define nullptr 0
using namespace std;
int main()
{
BiTree<int> tree1;
Node<int> *psrch_ans_node;
int srch_data,del_data;
tree1.addNode();
cout<<"先序遍历"<<endl;
tree1.preOrder();
cout<<endl<<"中序遍历"<<endl;
tree1.inOrder();
cout<<endl<<"后序遍历"<<endl;
tree1.postOrder();
cout<<endl<<"层序遍历"<<endl;
tree1.queueLevelOrder();
cout<<endl<<"请输入要查找的数据:";
cin>>srch_data;
psrch_ans_node = tree1.srchDataBST(srch_data);
if(psrch_ans_node)
cout<<psrch_ans_node->data;
//cout<<endl<<"请输入要删除的数据:";
//cin>>del_data;
//tree1.delData(del_data);
//cout<<"先序遍历"<<endl;
//tree1.preOrder();
cout<<endl<<"树叶们"<<endl;
tree1.getLeaveNum(1);
cout<<"\n一共有 "<<tree1.getLeaveNum(0)<<" 片树叶"<<endl;
//cout<<endl<<tree1.getTreeHight();
//cout<<endl<<tree1.getTreeWidth();
tree1.showLeaveToRootWay();
getch();
return 0;
}
代码执行效果