数据结构--二叉树(C++)

零、二叉树解决的问题

通过学习数组和链表,前者可以在常数时间内找到目标对象,但是插入和删除操作,都需要耗费线性的时间。后者则可以在常数时间内进行插入和删除,但是查找某一元素,则需要线性时间。很显然各有利弊,所以我们能不能选用一种更好的结构呢?树结构则是很好的选择。

在这里我们以二叉树为例,虽为特例,但是我们都可以将任何有序的多叉树转换为二叉树。

一、BinNode类的声明与实现

二叉树的结点包含数据域、左孩子指针、右孩子指针、双亲指针。

#define BinNodePosi(T) BinNode<T>*
template<typename T> struct BinNode {
    T data;
    BinNodePosi(T) lChild;
    BinNodePosi(T) rChild;
    BinNodePosi(T) parent;
    //构造函数
    BinNode():parent(NULL),lChild(NULL),rChild(NULL){}
    BinNode(T e,BinNodePosi(T) p=NULL,BinNodePosi(T) lc=NULL,BinNodePosi(T) rc=NULL):data(e),parent(p),lChild(lc),rChild(rc){}
    //开放接口
    BinNodePosi(T) insertAsLC(T const & e);
    BinNodePosi(T) insertAsRC(T const & e);
    bool IsRoot(BinNodePosi(T) p) {return !(p->parent);}
    bool IsLChild(BinNodePosi(T) p) {return !IsRoot(p)&&(p==p->parent->lChild);}
    bool IsRChild(BinNodePosi(T) p) { return !IsRoot(p)&&(p==p->parent->rChild);}

};
//作为当前结点的左孩子插入新结点
template<typename T>
BinNodePosi(T) BinNode<T>::insertAsLC(T const & e) {
    return lChild=new BinNode(e,this);
}
//作为当前结点的右孩子插入新结点
template<typename T>
BinNodePosi(T) BinNode<T>::insertAsRC(T const & e) {
    return rChild=new BinNode(e,this);
}

二、BinTree的声明与实现

#include "BinNode.h"
#include "enqueue.h"
template<typename T> class BinTree {
protect:
    int _size;//规模
    BinNodePosi(T) _root;
public:
    BinTree():_size(0),_root(NULL){}
    ~BinTree(){if(0<_size) remove(_root);}

public:
    int size() const {return _size;}
    bool empty() const {return !_root;}           //判空
    BinNodePosi(T) const root() { return _root;}  //返回根结点
    BinNodePosi(T) insertAsRoot(T const & e);     //插入根结点
    BinNodePosi(T) insertAsLC(BinNodePosi(T) p,T const & e);
    BinNodePosi(T) insertAsRC(BinNodePosi(T) p,T const & e);
    void remove(BinNodePosi(T) p);                //删除以p为根结点的子树
    //遍历
    void travPre(BinNodePosi(T) p,T visit);  //先序遍历
    void travIn(BinNodePosi(T) p,T visit);   //中序遍历
    void travPosi(BinNodePosi(T) p,T visit); //后序遍历
    void travLeave(BinNodePosi(T) p,T visit);//层序遍历
};
//作为当前结点的右孩子插入
template<typename T>
BinNodePosi(T) BinTree<T>::insertAsLC(BinNodePosi(T) p,T const & e) {
    _size++;p->insertAsLC(e);
    return p->lChild;
}
//作为当前结点的左孩子插入
template<typename T>
BinNodePosi(T) BinTree<T>::insertAsRC(BinNodePosi(T) p,T const & e) {
    _size++;p->insertAsRC(e);
    return p->rChild;
}
/插入根结点
template<typename T>
BinNodePosi(T) BinTree<T>::insertAsRoot(T const & e) {
    _size=1;
    return _root=new BinNode<T>(e);
}
//删除以p为根节点的子树
template<typename T>
void BinTree<T>::remove(BinNodePosi(T) p) {
    if(!x) return 0;
    int n=1+remove(p->lChild)+remove(p->rChild);
    delete p;
    _size-=n;
}
//递归版先序遍历
template<typename T>
void BinTree<T>::travPre(BinNodePosi(T) p,T visit) {
    if(!x) return;
    visit(p->data);
    travPre(x->lChild,visit);
    travPre(x->rChild,visit);
}
//递归版中序遍历
template<typename T>
void BinTree<T>::travIn(BinNodePosi(T) p,T visit) {
    if(!x) return;
    travPre(x->lChild,visit);
    visit(p->data);
    travPre(x->rChild,visit);
}
//递归版后序遍历
template<typename T>
void BinTree<T>::travPost(BinNodePosi(T) p,T visit) {
    if(!x) return;
    travPre(x->lChild,visit);
    travPre(x->rChild,visit);
    visit(p->data);
}
//层序遍历
template<typename T>
void BinTree<T>::travLevel(T visit) {
    Queue<BinNodePosi(T)> Q;
    Q.enqueue(this);
    while(!Q.empty()) {
        BinNodePosi(T) x=Q.dequeue();visit(x->data);
        if(x->lChild) Q.enqueue(x->lChild);
        if(x->rChild) Q.enqueue(x->rChild);
    }
}

以上二叉树的先序遍历,中序遍历,后序遍历算法为递归版,层序遍历借助队列实现层序的访问。

猜你喜欢

转载自blog.csdn.net/u013635579/article/details/78439674