BinaryTreesTravel

BinaryTreesTravel

代码来自张铭的数据结构与算法
此篇文章仅为记录代码
略简略,不易阅读
以下有7种周游算法
深度优先搜索

  • 前序递归/非递归
    . 中序递归/非递归
    . 后序递归/非递归
    广度优先搜索
    仅供参考
#include<iostream>
#include<stack>
using namespace std;
//空间时间复杂度均为O(n)
//二叉树结点
template<class T>
class BinaryTreeNode{
    friend class BinaryTree<T>;
    private:
        T info;
    public:
        BinaryTreeNode();
        BinaryTreeNode(const T& ele);
        BinaryTreeNode(const T& ele,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;//判断当前结点是否为叶节点
        BinaryTreeNode<T>&  operator = (const BinaryTreeNode<T>& Node)//重载赋值操作符
}

//二叉树
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);//返回当前结点的父节点
        BinaryTreeNode<T>* leftSibling(BinaryTreeNode<T>* current);//返回当前结点的左兄弟
        BinaryTreeNode<T>* rightSibling(BinaryTreeNode<T>* current);//返回当前结点的右兄弟

        void createTree(const T& info,BinaryTree<T>&leftTree,BinaryTree<T>&rightTree);//创建新树

        void preOrder(BinaryTreeNode<T>* root);//前序周游二叉树
        void inOrder(BinaryTreeNode<T>* root);//中序周游二叉树
        void postOrder(BinaryTreeNode<T>* root);//后序周游二叉树
        void levelOrder(BinaryTreeNode<T>* root);//按层次周游二叉树
        void deleteBinaryTree(BinaryTreeNode<T>* 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::postOrder(BinaryTreeNode<T>* root)
{
    if(root!=NULL){
        postOrder(root->leftChild());
        postOrder(root->rightchild());
        visit(root->value());
    }
}
//非递归版
//栈存所有非空右子树的结点
template<class T>
void BinaryTree::preOrderWithoutRecursion(BinaryTreeNode<T>* root)
{
    stack<BinaryTreeNode<T>* > aStack;
    BinaryTreeNode<T>* point=root;
    aStack.push(NULL);//栈底监视哨

    while(point){
        visit(point->value());//访问当前结点
        if(point->rightChild()!=NULL)//非空右孩子入栈
        {
            aStack.push(point->rightChild());
        }
        if(point->leftChild()!=NULL)
        {
            visit(point->value());//左路下降
            point=point->leftChild();
        }
        else{                       //左子树访问完毕,转向访问右子树
            point=aStack.top();     //获得栈顶元素
            aStack.pop();           //栈顶元素退栈
        }
    }
}
//中序,存的是根节点
template<class T>
void BinaryTree::inOrderWithoutRecursion(BinaryTreeNode<T>* root)
{
    stack<BinaryTreeNode<T>*> aStack;
    BinaryTreeNode<T>* point=root;
    while(!aStack.empty()||point)
    {
        if(point)
        {
            aStack.push(point);//当前指针入栈(根节点)
            point=point->leftChild();//左路下降
        }
        else
        {
            point=aStack.top();//左子树访问完毕,转向访问右子树,获得栈顶元素
            aStack.pop();//栈顶元素退栈
            visit(point->value());//访问当前结点
            point=point->rightChild();//指针指向右孩子
        }
    }
}

//后序
enum Tags{left,right};//定义枚举类型标志位
template<class T>
class StackElement{
    public:
    BinaryTreeNode* point;//指向树结点的指针(各个根节点)
    Tags tag;               //标志位
}
template<class T>
void BinaryTree::postOrderWithoutRecursion(BinaryTreeNode<T>* root)
{
    StackElement<T> element;
    stack<StackElement<T>> aStack;
    BinaryTreeNode<T>* point;
    if(root==NULL)                  //如果是空树则返回
        return;
    else 
        point=root;
    while(!aStack.empty()||point)   
    {
        while(point!=NULL)          //如果当前指针非空则压栈并下降到最左子树
        {
            element.point=point;
            element.tag=left;       //置标志位为left。进入左子树
            aStack.push(element);   
            point=point->leftChild();
        }
        element=aStack.top();       //获得栈顶元素
        aStack.pop();               //栈顶元素退栈
        point=element.point;        
        if(element.tag==left)       //如果从左子树返回
        {
            element.tag=right;      //置标志位为right,进入右子树
            aStack.push(element);   
            point=point->rightChild();
        }
        else
        {                            //如果从右子树返回,
            visit(point->value());  //访问当前结点
            point=NULL;             //置point指针为空,以继续弹栈
        }
    }
}
//时间O(n)
//最大存储空间(有数目最多的一层决定)(n+1)/2
//广度优先周游二叉树
//一层一层的按次序搜下去
template<class T>
void BinaryTree<T>::levelOrder(BinaryTreeNode<T>* root)
{
    using std::queue;
    queue<BinaryTreeNode<T>*> aQueue;
    BinaryTreeNode<T>* point=root;

    if(point)
        aQueue.push(point);     //根节点入队列
    while(!aQueue.empty())      //队列非空
    {
        point=aQueue.front();   //获得队列首节点
        aQueue.pop();           //当前结点出队列
        visit(point->value());  //访问当前结点
        if(point->leftChild()!=NULL)
            aQueue.push(point->leftChild());//左子树进队列
        if(point->rightChild()!=NULL)
            aQueue.push(point->rightChild());//右子树进队列
    }    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值