二叉树类和DFS,BFS

二叉树结点类,二叉树类;二叉树前序,中序,后序遍历(递归与非递归),层序遍历。

  • DFS深度搜索算法
  • 非递归前序遍历:访问左结点,保存左结点,使用栈。
  • 非递归中序遍历:遇到结点入栈,遍历左子树;遍历完左子树,从栈定弹出结点,遍历右子树,使用栈。
  • 非递归后序遍历:栈不空当前结点也不空,沿着左路下降入栈,如果从左边返回的然后处理邮编,如果从右边返回,访问该节点,使用栈。
  • BFS宽度搜索算法
  • 非递归层序遍历:使用队列。

值得学习的地方:友元类的定义;编程风格endwhile,endif;递归与非递归的转换

#include <iostream>
#include <stack>
#include <queue>
using namespace std;

template <class T> class BinaryTree;
template <class T>
class BinaryTreeNode {                          // 二叉树结点类
friend class BinaryTree<T>;                     //声明二叉树为结点类的友元类,便于访问私有数据成员
private:
    T  info;                                    //二叉树结点数据域
    BinaryTreeNode<T>* left;                    //二叉树结点指向左子树的指针
    BinaryTreeNode<T>* right;                   //二叉树结点指向左子树的指针

public:
    BinaryTreeNode();                           //缺省构造函数
    BinaryTreeNode(const T& inf);               //给定数据的构造函数
    BinaryTreeNode(const T& inf, BinaryTreeNode<T>* l, BinaryTreeNode<T>* r);//给定了结点值和左右子树的构造函数
    T  value() const;                           //返回当前结点的数据
    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
    BinaryTreeNode<T>& operator = (const BinaryTreeNode<T>& Node){this = Node;};//重载赋值操作符
};


//****** BinaryTreeNode Implementation *******//

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

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

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

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

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)  {  //设置当前结点的数据域
    info = val;
}

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


enum Tags{Left,Right};          //枚举类型

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

template <class T>
class BinaryTree {
private:
    BinaryTreeNode<T>*  root;                   //二叉树根结点
public:
    BinaryTree(){root = NULL;};                 //构造函数
    ~BinaryTree() {DeleteBinaryTree(root);};    //析构函数
    bool isEmpty() const;                       //判定二叉树是否为空树
    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结点的右兄弟
    void CreateTree(const T& info, BinaryTree<T>& leftTree, BinaryTree<T>& rightTree);
    //构造一棵以info为根、leftTree和rightTree为左右子树的新二叉树
    void PreOrder(BinaryTreeNode<T>* root);                 //递归前序周游二叉树或其子树
    void InOrder(BinaryTreeNode<T>* root);                  //递归中序周游二叉树或其子树
    void PostOrder(BinaryTreeNode<T>* root);                //递归后序周游二叉树或其子树
    void PreOrderWithoutRecursion(BinaryTreeNode<T>* root); //非递归前序周游二叉树或其子树
    void InOrderWithoutRecursion(BinaryTreeNode<T>* root);  //非递归中序周游二叉树或其子树
    void PostOrderWithoutRecursion(BinaryTreeNode<T>* root);//非递归后序周游二叉树或其子树
    void LevelOrder(BinaryTreeNode<T>* root);               //按层次周游二叉树或其子树
    void DeleteBinaryTree(BinaryTreeNode<T>* root);         //删除二叉树或其子树
    void Visit(T Value) {cout << Value;};                   //访问
};

//**********  BianryTree Implementation  ***********//
template<class T>
bool BinaryTree<T>:: isEmpty() const  {      //判定二叉树是否为空树
    return ( root? false : true);
}

template<class T>
BinaryTreeNode<T>* BinaryTree<T>::Parent(BinaryTreeNode<T>* current)  {
    using std::stack;                           //使用STL中的stack
    stack<BinaryTreeNode<T>* > aStack;
    BinaryTreeNode<T>* pointer = root;          //保存输入参数
    if(NULL != root && NULL != current)  {
        while(!aStack.empty() || pointer)    {
            if (pointer)  {
                if(current == pointer->leftchild() ||current == pointer->rightchild()) //如果当前pointer的孩子就是current,返回parent
                    return pointer;
                aStack.push(pointer);               //当前结点地址入栈
                pointer = pointer->leftchild();     //当前链接结构指向左孩子
            }
            else  {                                 //左子树访问完毕,转向访问右子树
                pointer = aStack.top();             //栈顶元素退栈
                aStack.pop();
                pointer = pointer->rightchild();    //当前链接结构指向右孩子
            }//endif
        } //endwhile
    }//endif
}

template<class T>
BinaryTreeNode<T>* BinaryTree<T>::LeftSibling(BinaryTreeNode<T>* current)  {
    //返回current结点的左兄弟
    if(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)  {
        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& info, BinaryTree<T>& leftTree, BinaryTree<T>& rightTree)  {
    //由左子树leftTree、右子树rightTree和数据元素info创建一棵新树,根结点是info
    //其中this、leftTree、rightTree必须是不同的三棵树
    root = new BinaryTreeNode<T>(info, 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>
void BinaryTree<T>:: InOrder (BinaryTreeNode<T>* root)  {  //中序周游二叉树
    if(root != NULL)  {
        InOrder (root->leftchild());            //访问左子树
        Visit(root->value());                   //访问当前结点
        InOrder (root->rightchild());           //访问右子树
    }
}

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>
void BinaryTree<T>::PreOrderWithoutRecursion(BinaryTreeNode<T>* root)  {//非递归前序周游二叉树或其子树
    using std::stack;                           //使用STL中的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();    //当前链接结构指向右孩子
        }//endif
    } //endwhile
}

template<class T>
void BinaryTree<T>::InOrderWithoutRecursion(BinaryTreeNode<T>* root)  {
    //非递归中序周游二叉树或其子树
    using std::stack;                           //使用STL中的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();
            aStack.pop();                       //栈顶元素退栈
            Visit(pointer->value());            //访问当前结点
            pointer = pointer->rightchild();    //当前链接结构指向右孩子
        }
    } //endwhile
}

template<class T>
void BinaryTree<T>::PostOrderWithoutRecursion(BinaryTreeNode<T>* root)  {
    //非递归后序周游二叉树或其子树
    using std::stack;                       //使用STL栈部分
    StackElement<T> element;
    stack<StackElement<T > > aStack;        //栈申明
    BinaryTreeNode<T>* pointer;
    if(root == NULL)
        return;                             //空树即返回
    else pointer = root;                    //保存输入参数

    while (!aStack.empty() || pointer) {
        while (pointer != NULL) {
            element.pointer = pointer;
            element.tag = Left;
            aStack.push(element);
            pointer = pointer->leftchild(); //沿左子树方向向下周游
        }

        element = aStack.top();
        aStack.pop();                       //托出栈顶元素
        pointer = element.pointer;

        if (element.tag == Left){
            //从左子树回来
            element.tag = Right;
            aStack.push(element);
            pointer = pointer->rightchild();
        }
        else {                              //从右子树回来
            Visit(pointer->value());        //访问当前结点
            pointer = NULL;
        }
    }
}

template<class T>
void BinaryTree<T>::LevelOrder(BinaryTreeNode<T>* root)    {
    //按层次周游二叉树或其子树
    using std::queue;                           //使用STL的队列
    queue<BinaryTreeNode<T>*> aQueue;
    BinaryTreeNode<T>* pointer = root;          //保存输入参数
    if (pointer)
        aQueue.push(pointer);                   //根结点入队列
    while (!aQueue.empty())  {                  //队列非空
        pointer = aQueue.front();               //取队列首结点
        aQueue.pop();                           //当前结点出队列
        Visit(pointer->value());                //访问当前结点
        if(pointer->leftchild())
            aQueue.push(pointer->leftchild());  //左子树进队列
        if(pointer->rightchild())
            aQueue.push(pointer->rightchild()); //右子树进队列
    }
}



int main() {
    //建一棵树(如图5.5所示)
    BinaryTree<char> a, b, c, d, e, f, g, h, i, nulltree;
    d.CreateTree('D', nulltree, nulltree);
    g.CreateTree('G', nulltree, nulltree);
    h.CreateTree('H', nulltree, nulltree);
    i.CreateTree('I', nulltree, nulltree);
    f.CreateTree('F', h, i);
    e.CreateTree('E', g, nulltree);
    b.CreateTree('B', d, e);
    c.CreateTree('C', nulltree, f);
    a.CreateTree('A', b, c);

    //前序周游二叉树
    cout << "Preorder sequence is: "<<endl;
    a.PreOrder(a.Root());                   //递归
    cout << endl;
    cout << "Preorder sequence Without Recursion is: " <<endl;
    a.PreOrderWithoutRecursion(a.Root());   //非递归
    cout << endl;

    //中序周游二叉树
    cout << "Inorder sequence is: "<<endl;
    a.InOrder(a.Root());                    //递归
    cout << endl;
    cout << "Inorder sequence Without Recursion is: " <<endl;
    a.InOrderWithoutRecursion(a.Root());    //非递归
    cout << endl;

    //后序周游二叉树
    cout << "Postorder sequence is: "<<endl;
    a.PostOrder(a.Root());                  //递归
    cout << endl;
    cout << "Postorder sequence Without Recursion is: " <<endl;
    a.PostOrderWithoutRecursion(a.Root());  //非递归
    cout << endl;

    //root
    cout << "Root is: " << a.Root()->value() <<endl;

/*    //delete tree
    a.DeleteBinaryTree(a.Root());
    cout<<"Tree is deleted."<<endl;        //没有问题,在析构函数中调用
*/
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值