二叉树基础-二叉树类模板的实现(数据结构基础 第5周)

这里参考了课本配套的程序简单实现了二叉树类模板,主要包含了二叉树的创建和各种遍历方法。
对于二叉树的建立,这里使用的是前序遍历的方法创建的二叉树,具体如下:
二叉树基础-二叉树类模板的实现(数据结构基础 第5周)_第1张图片
这里我使用的下图中的二叉树作为测试案例:

具体不说了,详见代码吧。
源码
//test.cpp

#include <iostream>
#include "BinaryTree.h"
#include "BinaryTreeNode.h"
#include <vector>
using namespace std;

//前序方法递归创建二叉树
BinaryTreeNode<char>* createTree() {
    BinaryTreeNode<char> *p;//这是使用局部变量是有风险的,函数结束后会被释放
    char ch;
    cin >> ch;
    if (ch=='#'){
        return NULL;
    }
    p = new BinaryTreeNode<char>(ch);
    p->setLeftchild(createTree());
    p->setRightchild(createTree());
    return p;
} 

void printTrsverse(const vector<char>& v) {
    for (int i=0; i<v.size(); i++)
    {
        cout << v.at(i);
    }
    cout << endl;
}

//示例,输入"ABD##EG###C#FH##I##"
int main() {
    BinaryTree<char> tr;
    tr.Initialize(createTree());
    vector<char> v;
    v=tr.traversePreOrder();
    cout << "前序递归遍历:" << endl;
    printTrsverse(v);

    v=tr.traverseInOrder();
    cout << "中序递归遍历:" << endl;
    printTrsverse(v);

    v=tr.traversePostOrder();
    cout << "后序递归遍历:" << endl;
    printTrsverse(v);

    v=tr.traversePreOrderWithoutRecusion();
    cout << "前序非递归遍历:" << endl;
    printTrsverse(v);

    v=tr.traverseInOrderWithoutRecusion();
    cout << "中序非递归遍历:" << endl;
    printTrsverse(v);

    v=tr.traversePostOrderWithoutRecusion();
    cout << "后序非递归遍历:" << endl;
    printTrsverse(v);

    v=tr.traversePostOrderWithoutRecusion2();
    cout << "后序非递归遍历2:" << endl;
    printTrsverse(v);

    v=tr.traverseLevelOrder();
    cout << "层次遍历:" << endl;
    printTrsverse(v);
    return 0;
}

//BinaryTree.h

#pragma once

#include "BinaryTreeNode.h"
#include <stack>
#include <queue>
#include <vector>
using namespace std;


enum Tags{Left,Right};

template <class T>
class StackElement
{
public:
    BinaryTreeNode<T>* pointer;
    Tags tag;
};

template <class T>
class BinaryTree  
{
private:
    BinaryTreeNode<T>*  root;                               //二叉树根结点指针
    vector<T> elements;  //用于保存遍历的元素
private:
    void Visit(T elem) {elements.push_back(elem);};  //遍历访问元素的值
    void PreOrder(BinaryTreeNode<T>* root); //从root前序遍历二叉树或其子树(递归部分)
    void InOrder(BinaryTreeNode<T>* root);  //从root中序遍历二叉树或其子树(递归部分) 
    void PostOrder(BinaryTreeNode<T>* root); //从root后序遍历二叉树或其子树(递归部分) 
    void PreOrderWithoutRecusion(BinaryTreeNode<T>* root); //从root非递归前序遍历二叉树或其子树(递归部分) 
    void InOrderWithoutRecusion(BinaryTreeNode<T>* root);  //从root非递归中序遍历二叉树或其子树(递归部分) 
    void PostOrderWithoutRecusion(BinaryTreeNode<T>* root);  //从root非递归后序遍历二叉树或其子树 (递归部分)
    void PostOrderWithoutRecusion2(BinaryTreeNode<T>* root);  //从root非递归后序遍历二叉树或其子树, 另一个版本(递归部分)
    void LevelOrder(BinaryTreeNode<T>* root);  //按层次遍历二叉树或其子树
    BinaryTreeNode<T>* GetParent(BinaryTreeNode<T>* root,BinaryTreeNode<T>* current);//递归由root结点查找current结点的父结点

public:
    BinaryTree(){root=NULL;};                               //构造函数
    virtual ~BinaryTree(){DeleteBinaryTree(root);};            //析构函数
    bool isEmpty() const                            
    {return ((root)?TRUE:FALSE);};                          //判定二叉树是否为空树

    void Initialize(BinaryTreeNode<T>* pointer) {root=pointer;};    

    BinaryTreeNode<T>* Root() {return root;};  //返回二叉树根节点
    BinaryTreeNode<T>* Parent(BinaryTreeNode<T>* current); //返回current结点的父结点指针 
    BinaryTreeNode<T>* LeftSibling(BinaryTreeNode<T>* current); //返回current结点的左兄弟 
    BinaryTreeNode<T>* RightSibling(BinaryTreeNode<T>* current);//返回current结点的右兄弟

    //以elem作为根结点,leftTree作为树的左子树,rightTree作为树的右子树,构造一棵新的二叉树
    void CreateTree(const T& elem, BinaryTree<T>& leftTree, BinaryTree<T>& rightTree);  
    void DeleteBinaryTree(BinaryTreeNode<T>* root);     //递归删除二叉树或其子树 

    vector<T> traversePreOrder();  //从根节点前序遍历,以下依次对应
    vector<T> traverseInOrder();
    vector<T> traversePostOrder();
    vector<T> traversePreOrderWithoutRecusion();
    vector<T> traverseInOrderWithoutRecusion();
    vector<T> traversePostOrderWithoutRecusion();
    vector<T> traversePostOrderWithoutRecusion2();
    vector<T> traverseLevelOrder();     
};

template<class T>
BinaryTreeNode<T>* BinaryTree<T>::GetParent(BinaryTreeNode<T>* root,BinaryTreeNode<T>* current)
{
    //从二叉树的root结点开始,查找current结点的父结点
    BinaryTreeNode<T>* temp;
    if(root==NULL)
        return NULL;
    //找到父结点
    if((root->leftchild()==current)||(root->rightchild()==current))
        return root;
    //递归寻找父结点
    if((temp=GetParent(root->leftchild(),current))!=NULL)
        return temp;
    else return GetParent(root->rightchild(),current);  
}

template<class T>
BinaryTreeNode<T>* BinaryTree<T>::Parent(BinaryTreeNode<T>* current)  //返回current结点的父结点指针
{
    if((current==NULL)||(current==root))
        return NULL;                    //空结点或者current为根结点时,返回NULL
    return GetParent(root,current);     //调用递归函数寻找父结点
}

template<class T>
BinaryTreeNode<T>* BinaryTree<T>::LeftSibling(BinaryTreeNode<T>* current)  //返回current结点的左兄弟
{
    if(current)                                         //current不为空
    {
        BinaryTreeNode<T>* temp=Parent(current);    //返回current结点的父结点
        if((temp==NULL)||current==temp->leftchild())
            return  NULL;           //如果父结点为空,或者current没有左兄弟
        else return temp->leftchild();
    }
    return NULL;
}

template<class T>
BinaryTreeNode<T>* BinaryTree<T>::RightSibling(BinaryTreeNode<T>* current) //返回current结点的右兄弟
{
    if(current)                                 //current不为空
    {
        BinaryTreeNode<T>* temp=Parent(current);//返回current结点的父结点
        if((temp==NULL)||current==temp->rightchild())
            return  NULL;                   //如果父结点为空,或者current没有右兄弟
        else return temp->rightchild();
    }
    return NULL;
}

template<class T>
void BinaryTree<T>::CreateTree(const T& elem, BinaryTree<T>& leftTree, BinaryTree<T>& rightTree) //以elem作为根结点,leftTree作为树的左子树,rightTree作为树的右子树,构造一棵新的二叉树
{
    root=new BinaryTreeNode<T>(elem,leftTree.root,rightTree.root);  //创建新树
    leftTree.root=rightTree.root=NULL;                              //原来两棵子树的根结点指空,避免访问
}

template<class T>
void BinaryTree<T>::DeleteBinaryTree(BinaryTreeNode<T>* root)       //递归删除二叉树或其子树
{
    if(root)
    {
        DeleteBinaryTree(root->left);
        DeleteBinaryTree(root->right);
        delete root;
    };
};

template<class T>
void BinaryTree<T>::PreOrder(BinaryTreeNode<T>* root)               //前序遍历二叉树或其子树
{
    if(root!=NULL)
    {
        Visit(root->value());   
        PreOrder(root->leftchild());            //访问左子树
        PreOrder(root->rightchild());           //访问右子树
    }
};
template<class T>
vector<T> BinaryTree<T>::traversePreOrder() 
{
    elements.clear();
    PreOrder(root);
    return elements;
}

template<class T>
void BinaryTree<T>::InOrder(BinaryTreeNode<T>* root)                //中序遍历二叉树或其子树
{
    if(root!=NULL)
    {
        InOrder (root->leftchild());            //访问左子树
        Visit(root->value());           //访问当前结点
        InOrder (root->rightchild());           //访问右子树
    }
}
template<class T>
vector<T> BinaryTree<T>::traverseInOrder() 
{
    elements.clear();
    InOrder(root);
    return elements;
}

template<class T>
void BinaryTree<T>::PostOrder(BinaryTreeNode<T>* root)              //后序遍历二叉树或其子树
{
    if(root!=NULL)
    {
        PostOrder(root->leftchild());           //访问左子树
        PostOrder (root->rightchild());         //访问右子树
        Visit(root->value());           //访问当前结点
    }
}
template<class T>
vector<T> BinaryTree<T>::traversePostOrder() 
{
    elements.clear();
    PostOrder(root);
    return elements;
}

template<class T>
void BinaryTree<T>::PreOrderWithoutRecusion(BinaryTreeNode<T>* root)//非递归前序遍历二叉树或其子树
{
// using std::stack;

    stack<BinaryTreeNode<T>* > aStack;
    BinaryTreeNode<T>* pointer=root;                //保存输入参数 

    while(!aStack.empty()||pointer)             
    {
        if(pointer){
            Visit(pointer->value());        //访问当前结点
            aStack.push(pointer);                   //当前结点地址入栈
            pointer=pointer->leftchild();           //当前链接结构指向左孩子
        }
        else {                                          //左子树访问完毕,转向访问右子树
            pointer=aStack.top();                   //栈顶元素退栈 
            aStack.pop();
            pointer=pointer->rightchild();      //当前链接结构指向右孩子
        } //else
    } //while
}
template<class T>
vector<T> BinaryTree<T>::traversePreOrderWithoutRecusion() 
{
    elements.clear();
    PreOrderWithoutRecusion(root);
    return elements;
}

template<class T>
void BinaryTree<T>::InOrderWithoutRecusion(BinaryTreeNode<T>* root) //非递归中序遍历二叉树或其子树
{
// using std::stack;
    stack<BinaryTreeNode<T>* > aStack;
    BinaryTreeNode<T>* pointer=root;                //保存输入参数 

    while(!aStack.empty()||pointer)             
    {
        if(pointer){
            aStack.push(pointer);                   //当前结点地址入栈
            pointer=pointer->leftchild();           //当前链接结构指向左孩子
        }
        else {                                          //左子树访问完毕,转向访问右子树
            pointer=aStack.top();               
            Visit(pointer->value());        //访问当前结点
            pointer=pointer->rightchild();      //当前链接结构指向右孩子
            aStack.pop();                           //栈顶元素退栈 
        } //else
    } //while
}
template<class T>
vector<T> BinaryTree<T>::traverseInOrderWithoutRecusion() 
{
    elements.clear();
    InOrderWithoutRecusion(root);
    return elements;
}

template<class T>
void BinaryTree<T>::PostOrderWithoutRecusion(BinaryTreeNode<T>* root)//非递归后序遍历二叉树或其子树
{
// using std::stack;
    StackElement<T> element;
    stack<StackElement<T > > aStack;
    BinaryTreeNode<T>* pointer;
    if(NULL==root)
        return;                                     //空树即返回
    else pointer=root;
    while(true)
    {
        //进入左子树
        while(pointer!=NULL)
        {
            element.pointer=pointer;
            element.tag=Left;
            aStack.push(element);
            pointer=pointer->leftchild();
        }
        //托出栈顶元素
        element=aStack.top();
        aStack.pop();
        pointer=element.pointer;
        //从右子树回来
        while(element.tag==Right)
        {
            Visit(pointer->value());        //访问当前结点
            if(aStack.empty())
                return;
            else
            {
                element=aStack.top();
                aStack.pop();
                pointer=element.pointer;
            }
        }
        //从左子树回来
        element.tag=Right;
        aStack.push(element);
        pointer=pointer->rightchild();
    }
}
template<class T>
vector<T> BinaryTree<T>::traversePostOrderWithoutRecusion() 
{
    elements.clear();
    PostOrderWithoutRecusion(root);
    return elements;
}

template<class T>
void BinaryTree<T>::PostOrderWithoutRecusion2(BinaryTreeNode<T>* root)
{//非递归后序遍历二叉树或其子树, 另一个版本
// using std::stack;
    stack<BinaryTreeNode<T>* > aStack;
    BinaryTreeNode<T> *p, *q;
    if(root==NULL)
        return;
    p=root;
    do{
        while(p!=NULL)                          //沿左路分支下降 
        {
            aStack.push(p);
            p=p->leftchild();
        }
        q=NULL;
        while(!aStack.empty())
        {
            p=aStack.top();
            aStack.pop();
            if(p->rightchild()==q)              //右子树为空或刚刚被访问过
            {
                Visit(p->value());      //访问当前结点
                q=p;
            }
            else
            {
                aStack.push(p);
                p=p->rightchild();
                break;
            }
        }
    }while(!aStack.empty());
}
template<class T>
vector<T> BinaryTree<T>::traversePostOrderWithoutRecusion2() 
{
    elements.clear();
    PostOrderWithoutRecusion2(root);
    return elements;
}

template<class T>
void BinaryTree<T>::LevelOrder(BinaryTreeNode<T>* root) //按层次遍历二叉树或其子树,这里使用队列来模拟
{
// using std::queue;
    queue<BinaryTreeNode<T>*> aQueue;
    BinaryTreeNode<T>* pointer=root;

    if(pointer)
        aQueue.push(pointer);
    while(!aQueue.empty())
    {
        pointer=aQueue.front();
        Visit(pointer->value());        //访问当前结点
        aQueue.pop();
        if(pointer->leftchild())
            aQueue.push(pointer->leftchild());
        if(pointer->rightchild())
            aQueue.push(pointer->rightchild());
    }
}
template<class T>
vector<T> BinaryTree<T>::traverseLevelOrder() 
{
    elements.clear();
    LevelOrder(root);
    return elements;
}

//BinaryTreeNode.h

#pragma once

template <class T> class BinaryTree;

template <class T>
class BinaryTreeNode  
{
friend class BinaryTree<T>;
private:
    T  element;                                         //二叉树结点数据域
    BinaryTreeNode<T>*  left;                           //二叉树结点指向左子树的指针
    BinaryTreeNode<T>*  right;                          //二叉树结点指向左子树的指针
public:
    BinaryTreeNode();
    BinaryTreeNode(const T& ele);                       //给定数据的构造函数
    BinaryTreeNode(const T& ele,BinaryTreeNode* l, BinaryTreeNode* r);//给定数据的左右指针的构造函数
    T  value() const;                                   //返回当前结点的数据
    BinaryTreeNode<T>& operator= (const BinaryTreeNode<T>& Node)
    {this=Node;};                                       //重载赋值操作符
    BinaryTreeNode<T>*  leftchild() const;              //返回当前结点指向左子树的指针
    BinaryTreeNode<T>*  rightchild() const;             //返回当前结点指向右子树的指针
    void  setLeftchild(BinaryTreeNode<T>*);             //设置当前结点的左子树
    void  setRightchild(BinaryTreeNode<T>*);            //设置当前结点的右子树
    void  setValue(const T& val);                       //设置当前结点的数据域
    bool  isLeaf() const;                               //判定当前结点是否为叶结点,若是返回true
};

template<class T>
BinaryTreeNode<T>::BinaryTreeNode()
{
    left=right=NULL;
}

template<class T>
BinaryTreeNode<T>::BinaryTreeNode(const T& ele) //给定数据的构造函数
{
    element=ele;
    left=right=NULL;
}

template<class T>
BinaryTreeNode<T>::BinaryTreeNode(const T& ele,BinaryTreeNode* l, BinaryTreeNode* r)
    //给定数据的左右指针的构造函数
{
    element=ele;
    left=l;
    right=r;
}

template<class T>
T  BinaryTreeNode<T>::value() const
{
    return element; 
}

template<class T>
BinaryTreeNode<T>*  BinaryTreeNode<T>::leftchild() const
{
    return left;                                //返回当前结点指向左子树的指针
}

template<class T>
BinaryTreeNode<T>*  BinaryTreeNode<T>::rightchild() const
{
    return right;                               //返回当前结点指向右子树的指针
}   

template<class T>
void  BinaryTreeNode<T>::setLeftchild(BinaryTreeNode<T>* subroot)//设置当前结点的左子树
{
    left=subroot;
}

template<class T>
void  BinaryTreeNode<T>::setRightchild(BinaryTreeNode<T>* subroot)//设置当前结点的右子树
{
    right=subroot;
}

template<class T>
void  BinaryTreeNode<T>::setValue(const T& val) //设置当前结点的数据域
{
    element = val; 
} 

template<class T>
bool  BinaryTreeNode<T>::isLeaf() const         //判定当前结点是否为叶结点,若是返回true
{
    return (left == NULL) && (right == NULL); 
}

———————————2016.7.8记———————————————————————————–
上述test.cpp的createTree函数是有风险的,因为每次在函数内定义一个新结点,这样在函数结束时就被释放了。关于此问题很容易被忽视,详见:二叉树基础-由中根序列和后根序列重建二叉树(数据结构基础 第5周)

你可能感兴趣的:(二叉树基础-二叉树类模板的实现(数据结构基础 第5周))