话不多说,直接上代码。
#include<iostream>
#include<queue>
#include<stack>
using namespace std;
class Node {
public:
char data;
Node * left;
Node * right;
};
class binaryTree{
public:
binaryTree(); //构造函数
~binaryTree(); //析构函数
int size(Node * BtNode); //返回二叉树节点总数
int height(int size); //通过节点数的二叉树最大层数
int height(Node * BtNode); //通过二叉树最左边节点所处的层数代表整体的层数
bool empty(); //判定二叉树是否为空
void creat(); //创建完全二叉树,遇到输入‘#’停止
void preOrder(Node * BtNode); //先序遍历(非递归)
void inOrder(Node * BtNode); //中序遍历(非递归)
void postOrder(Node * BtNode); //后序遍历(非递归)
void preOrderRe(Node * BtNode); //先序遍历(递归)
void inOrderRe(Node * BtNode); //中序遍历(递归)
void postOrderRe(Node * BtNode); //后序遍历(递归)
void levelOrder(Node * BtNode); //层次遍历
Node * getRoot(){ //返回二叉树的根节点
return root;
}
private:
Node * root;
};
//二叉树构造函数,对属性元素进行初始化的操作
binaryTree::binaryTree(){
root = NULL;
}
//二叉树的析构函数,不进行实现
binaryTree::~binaryTree(){
}
//二叉树的插入操作
//到底二叉树的插入应该如何进行
//还是使用上述的队列方法进行实现
void binaryTree::creat(){
queue <Node *> que;
char temp = ' ';
while(1){
cin>>temp;
if(temp == '#')
break;
Node * tempNode = new Node();
tempNode->data = temp;
tempNode->left = NULL;
tempNode->right = NULL;
if(root == NULL){
root = tempNode ;
que.push(tempNode);
}
else{
if(que.front()->left == NULL){
que.front()->left = tempNode;
que.push(tempNode);
}
else{
que.front()->right = tempNode;
que.push(tempNode);
que.pop();
}
}
}
}
bool binaryTree::empty(){
return (root == NULL);
}
void binaryTree::preOrder(Node * BtNode){
//使用非递归的方法先序遍历输出
//先序遍历 先根、再左、后右
//采用堆栈进行辅助
Node * current = BtNode;
stack <Node*>stk;
while(1){
while(current){
stk.push(current);
cout<<current->data<<" ";
current = current->left;
}
if(stk.empty())
break;
current = stk.top();
stk.pop();
current = current->right;
}
}
void binaryTree::inOrder(Node * BtNode){
//非递归型中序输出,先左、再根、后右
//使用栈的数据类型进行相应的辅助
Node * temp = BtNode;
stack <Node *>stk;
while(1){
while(temp){ //函数传进来的是树的根节点
stk.push(temp); //将途经的节点入栈
temp = temp->left; //首先遍历树的最左边节点,最终栈顶元素就是树的最左边节点
} //现在出现的是最左边节点的左边节点,为空值
if(stk.empty()){
break;
}
temp = stk.top(); //取出栈顶的节点,并将栈顶元素弹出
stk.pop();
cout<<temp->data<<" "; //输出前栈顶节点的数值
temp = temp->right;
}
}
void binaryTree::postOrder(Node * BtNode){
//使用非递归方式实现树的后序遍历
//先左、再右、后根
//与先前两种方式并不相同的是,对于一个子树的根节点需要访问两次,一次是访问左边节点之后的返回,另一个
//是右边节点的返回,但是如何对上述两种情况进行识别,这是一个较为困难的问题,
//我们利用previous记录刚刚访问过的节点,利用current代表当前节点(并且处于当前的栈顶),
//如果previous为current的双亲,则继续向下遍历,如果当前节点具有左孩子,则将其压入栈中,如果没有左孩子,
//看是否有右孩子,若都没有,则为叶子节点,那么将其值输出,并弹出栈顶元素
//如果previous为current的左孩子节点,则说明是从左子树返回。现在判定是否具有右孩子,如果有,则继续右子树遍历
//如果没有则将其值输出,并弹出栈顶元素
//如果时右孩子节点,则说明从右子树返回,输出值,并弹出栈
//后序遍历最重要的就是判定子树的右边子树是否访问过,如果没有访问过,再访问左边子树后,将当前节点转化为右边节点
//如果访问过,就直接进行值的输出,并弹出栈顶元素,同时将没有右边节点也称之为访问过了。
Node* current = BtNode; //初始化的时候定义其为根节点
stack <Node *> stk;
Node* topCurrent = NULL;
Node* previous = NULL;
while(current || !stk.empty()){ //如果当前访问的节点为空并且栈也为空,此时循环结束
//找到子树的最左边的节点
while(current){
stk.push(current); //将途经的节点压入栈中
current = current->left; //访问下一个左边节点
}
topCurrent = stk.top(); //得到栈顶元素
//判断右树是否被访问?
if(topCurrent->right == NULL || topCurrent->right == previous){
cout<<topCurrent->data<<" ";//右子结点为空也记作访问过,
previous = topCurrent;
stk.pop(); //对于该节点访问完毕,退栈,访问上一级节点
}
//右树没有被访问,
else{
current = topCurrent->right;
}
}
}
void binaryTree::preOrderRe(Node * BtNode){
if(BtNode){
cout<<BtNode->data<<" ";
preOrderRe(BtNode->left);
preOrderRe(BtNode->right);
}
}
void binaryTree::inOrderRe(Node * BtNode){
if(BtNode){
inOrderRe(BtNode->left);
cout<<BtNode->data<<" ";
inOrderRe(BtNode->right);
}
}
void binaryTree::postOrderRe(Node * BtNode){
if(BtNode){
postOrderRe(BtNode->left);
postOrderRe(BtNode->right);
cout<<BtNode->data<<" ";
}
}
//按照层次化的顺序对二叉树进行遍历
//使用队列作为辅助工具,类似于创建二叉树的过程
//就是按照从上到下,从左到右的顺序将树中的节点加入到队列中即可
void binaryTree::levelOrder(Node * BtNode){
queue <Node *> que;
que.push(BtNode);
while(!que.empty()){
cout<<que.front()->data<<" ";
if(que.front()->left){
que.push(que.front()->left);
}
if(que.front()->right){
que.push(que.front()->right);
}
que.pop();
}
}
//计算二叉树中节点的个数只需要分别返回左边节点以及右边节点的个数再加上1(两边子树的根节点)
int binaryTree::size(Node * BtNode){
if(BtNode == NULL){
return 0;
}
else
return (size(BtNode->left) + 1 + size(BtNode->right));
}
//计算二叉树的高度
//如果已知二叉树的节点个数,则可以使用相关的公式进行计算
//节点数n,高度h 2 ^(h-1) - 1 <= n <= 2 ^ h
int binaryTree::height(int size){
int height = 0;
while(size != 0){
height++;
size /= 2;
}
return height;
}
//利用二叉树最左边的节点所处的层数代表整体的层数 (仅适用于完全二叉树)
int binaryTree::height(Node * BtNode){
int height = 0;
while(BtNode){
height++;
BtNode = BtNode->left;
}
return height;
}
int main(){
binaryTree BT;
cout<<"二叉树是否为空:"<<BT.empty()<<endl;
BT.creat();
cout<<"二叉树是否为空:"<<BT.empty()<<endl;
cout<<"先序遍历为: ";
BT.preOrder(BT.getRoot());
cout<<endl;
cout<<"中序遍历为: ";
BT.inOrder(BT.getRoot());
cout<<endl;
cout<<"后序遍历为: ";
BT.postOrder(BT.getRoot());
cout<<endl;
cout<<"先序遍历(递归)为: ";
BT.preOrderRe(BT.getRoot());
cout<<endl;
cout<<"中序遍历(递归)为: ";
BT.inOrderRe(BT.getRoot());
cout<<endl;
cout<<"后序遍历(递归)为: ";
BT.postOrderRe(BT.getRoot());
cout<<endl;
cout<<"层次遍历为: ";
BT.levelOrder(BT.getRoot());
cout<<endl;
cout<<"二叉树的节点数目为:"<<BT.size(BT.getRoot())<<endl;
cout<<"二叉树的高度为:"<<BT.height(BT.size(BT.getRoot()))<<endl;
cout<<"二叉树的高度(树的最左边节点数)为:"<<BT.height(BT.getRoot())<<endl;
return 0;
}