1. 程式人生 > >資料結構--二叉樹(C++)

資料結構--二叉樹(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);
    }
}

以上二叉樹的先序遍歷,中序遍歷,後序遍歷演算法為遞迴版,層序遍歷藉助佇列實現層序的訪問。