二叉排序树

二叉查找树

1.概念

  二叉排序树可以是一颗空树,或者是具有以下性质的树:

  1.左子树如果不为空,左子树上所有节点的值均小于等于根节点的值

  2.右子树如果不为空。右子树上所有节点的值均大于等于根节点的值

  3.左右子树均为二叉排序树

2.实现

我们讨论二叉树的查找,插入,删除,遍历,线索化。 

#ifndef BST_H
#define BST_H
#include <iostream>
using namespace std;
template<typename T>
class Node
{
public:
    T Data;
    Node *LeftChild;
    Node *RightChild;
    Node(const T& data) : Data(data),
        LeftChild(nullptr),
        RightChild(nullptr){}
};
template<typename T>
class BST
{
public:
    BST() : Root(nullptr){}
    ~BST(){
        this->clear();
    }
    void clear()
    {   this->clear(Root); }
    bool isEmpty() const{
        return Root == nullptr;
    }
    void preorder(){//先序遍历
        preorder(Root);
    }
    void inorder(){//中序遍历
        inorder(Root);
    }
    void postorder(){//后序遍历
        postorder(Root);
    }
    T* search(const T&el) const{
        return search(root,el);
    }
    void breadthFirst();
    void iterativePreorder();//非递归先序
    void iterativeInorder();
    void iterativePostorder();
    void insert(const T&);
    void erase(Node<T> *&);
private:
    Node<T>* Root;
    void clear(Node<T>* node);
    void preorder(Node<T>* node);
    void inorder(Node<T>* node);
    void postorder(Node<T>* node);
    T* search(Node<T>* node,const T&el) const;
    void visit(Node<T> *p){
        cout << p->Data << endl;
    }
};

 

1.查找

    根据二叉排序树的概念,将查找值与树的节点比较,

  如果要查找的值小于节点的值,转向节点的左子树,

  如果要查找的值大于节点的值,转向节点的右子树。

  如果二者相同,则查找成功。

template<typename T>
T* BST::search(Node<T>* node,const T&el) const
{
    while(node)
        if(el == node->Data)
            return &node->Data;
        else if(el < node->Data)
            return node->LeftChild;
        else
            return node->RightChild;
    return nullptr;
}

2.树的广度优先遍历

  广度优先遍历,是指从最高层(或者最底层)开始,向下(或者向上)逐层的访问每个节点,在每个层次上,从左到右(或者从右到左)访问每个节点

。所以实际上,我们有四种不同的广度优先遍历方式。我们来完成从上到下,从左到右的广度优先遍历的实现。

template<typename T>
void BST::breadthFirst()
{
    std::queue<Node<T>*> nodeQueue;
    Node<T>* p = Root;
    if(p)
    {
        nodeQueue.push(p);
        while(!nodeQueue.empty())
        {
            p = nodeQueue.front();
            nodeQueue.pop();
            visit(p);
            if(p->LeftChild)
                nodeQueue.push(p->LeftChild);
            if(p->RightChild)
                nodeQueue.push(p->RightChild);
        }
    }
}

 

3.树的深度优先遍历的递归实现。

  深度优先遍历分为三种:

  1.先序遍历:先访问根节点,再访问左子树,右子树。访问子树时同样先访问子树的根节点,再访问子树的左子树,右子树。

  2.中序遍历:先访问左子树,再访问根节点,最后访问右子树。

  3.后序遍历:先访问左子树,再访问右子树,最后访问根节点。

  使用递归我们可以写出非常清晰明了的函数来实现树的深度遍历

  

template<typename T>
void BST::preorder(Node<T>* p)
{
    if(p)
    {
        visit(p);
        preorder(p->LeftChild);
        preorder(p->RightChild);
    }
}

template<typename T>
void BST::inorder(Node<T>* p)
{
    if(p)
    {
        inorder(p->LeftChild);
        visit(p);
        inorder(p->RightChild);
    }
}

template<typename T>
void BST::postorder(Node<T>* p)
{
    if(p)
    {
        postorder(p->LeftChild);
        postorder(p->RightChild);
        visit(p);
    }
}

 

  我们在函数中使用了双重递归,这对系统造成了沉重的负担。我们希望可以写出非递归版本的深度优先遍历函数。

  

4.树的深度优先遍历的非递归实现

 

posted @ 2017-03-20 21:00  是召不是昭  阅读(195)  评论(0编辑  收藏  举报