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

来源:互联网 发布:js 点击显示modal 编辑:程序博客网 时间:2024/06/06 00:24

零、二叉树解决的问题

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

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

一、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);    }}

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