二叉搜索树

转载 2013年12月05日 16:47:20

  • 二叉搜索树:继承于二叉树。二叉搜索树的性质:插入元素之后,中序遍历二叉搜索树时,输出结果为一个有序数组。
  • 注意的地方:类的提前声明,设置友元类访问私有数据

#include <iostream>
#include <stack>
#include <queue>
using namespace std;

template <class T> class BinarySearchTree;  // 类的提前声明
template <class T> class BinaryTree;        // 类的提前声明
template <class T>
class BinaryTreeNode                            // 二叉树结点类
{
    friend class BinaryTree<T>;                     //声明二叉树为结点类的友元类,便于访问私有数据成员
    friend class BinarySearchTree<T>;               //声明BinarySearchTree为结点类的友元类,便于访问私有数据成员
private:
    T  info;                                    //二叉树结点数据域
    BinaryTreeNode<T>* left;                    //二叉树结点指向左子树的指针
    BinaryTreeNode<T>* right;                   //二叉树结点指向左子树的指针

public:
    BinaryTreeNode();                           //缺省构造函数
    BinaryTreeNode(const T& inf);               //给定数据的构造函数
    BinaryTreeNode(const T& inf, 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;                       //判定当前结点是否为叶结点,若是返回true
    BinaryTreeNode<T>& operator = (const BinaryTreeNode<T>& Node)
    {
        this = Node;
    };//重载赋值操作符
};

//****** BinaryTreeNode Implementation *******//

template<class T>
BinaryTreeNode<T>::BinaryTreeNode()
{
    left = right = NULL;
}

template<class T>
BinaryTreeNode<T>::BinaryTreeNode(const T& inf)       //给定数据的构造函数
{
    info = inf;
    left = right = NULL;
}

template<class T>
BinaryTreeNode<T>::BinaryTreeNode(const T& inf, BinaryTreeNode* l, BinaryTreeNode* r)   //给定数据的左右指针的构造函数
{
    info = inf;
    left = l;
    right = r;
}

template<class T>
T  BinaryTreeNode<T>::value() const
{
    return info;
}

template<class T>
BinaryTreeNode<T>*  BinaryTreeNode<T>::leftchild() const     //返回当前结点指向左子树的指针
{
    return left;
}

template<class T>
BinaryTreeNode<T>*  BinaryTreeNode<T>::rightchild() const    //返回当前结点指向右子树的指针
{
    return right;
}

template<class T>
void  BinaryTreeNode<T>::setLeftchild(BinaryTreeNode<T>* subroot)    //设置当前结点的左子树
{
    left = subroot;
}

template<class T>
void  BinaryTreeNode<T>::setRightchild(BinaryTreeNode<T>* subroot)    //设置当前结点的右子树
{
    right = subroot;
}

template<class T>
void  BinaryTreeNode<T>::setValue(const T& val)     //设置当前结点的数据域
{
    info = val;
}

template<class T>
bool  BinaryTreeNode<T>::isLeaf() const             //判定当前结点是否为叶结点,若是返回true
{
    return (left == NULL) && (right == NULL);
}

enum Tags {Left,Right};         //枚举类型

template <class T>
class StackElement              //StackElement
{
public:
    BinaryTreeNode<T>* pointer;
    Tags tag;
};

template <class T>
class BinaryTree
{
    friend class BinarySearchTree<T>;//声明BinarySearchTree为二叉树类的友元类,便于访问私有数据成员root
private:
    BinaryTreeNode<T>*  root;                   //二叉树根结点
public:
    BinaryTree()
    {
        root = NULL;
    };                 //构造函数
    virtual ~BinaryTree()
    {
        DeleteBinaryTree(root);
    };    //析构函数
    bool isEmpty() const;                       //判定二叉树是否为空树
    BinaryTreeNode<T>* Root()
    {
        return root;
    };    //返回二叉树根结点
    BinaryTreeNode<T>* Parent(BinaryTreeNode<T>* current);//返回current的父结点
    BinaryTreeNode<T>* LeftSibling(BinaryTreeNode<T>* current);
    //返回current结点的左兄弟
    BinaryTreeNode<T>* RightSibling(BinaryTreeNode<T>* current);
    //返回current结点的右兄弟
    void CreateTree(const T& info, BinaryTree<T>& leftTree, BinaryTree<T>& rightTree);
    //构造一棵以info为根、leftTree和rightTree为左右子树的新二叉树
    void PreOrder(BinaryTreeNode<T>* root);                 //递归前序周游二叉树或其子树
    void InOrder(BinaryTreeNode<T>* root);                  //递归中序周游二叉树或其子树
    void PostOrder(BinaryTreeNode<T>* root);                //递归后序周游二叉树或其子树
    void PreOrderWithoutRecursion(BinaryTreeNode<T>* root); //非递归前序周游二叉树或其子树
    void InOrderWithoutRecursion(BinaryTreeNode<T>* root);  //非递归中序周游二叉树或其子树
    void PostOrderWithoutRecursion(BinaryTreeNode<T>* root);//非递归后序周游二叉树或其子树
    void LevelOrder(BinaryTreeNode<T>* root);               //按层次周游二叉树或其子树
    void DeleteBinaryTree(BinaryTreeNode<T>* root);         //删除二叉树或其子树
    void Visit(T Value)
    {
        cout << Value << " ";
    };                   //访问
};

//**********  BianryTree Implementation  ***********//
template<class T>
bool BinaryTree<T>:: isEmpty() const         //判定二叉树是否为空树
{
    return ( root? false : true);
}

template<class T>
BinaryTreeNode<T>* BinaryTree<T>::Parent(BinaryTreeNode<T>* current)
{
    using std::stack;                           //使用STL中的stack
    stack<BinaryTreeNode<T>* > aStack;
    BinaryTreeNode<T>* pointer = root;          //保存输入参数
    if(NULL != root && NULL != current)
    {
        while(!aStack.empty() || pointer)
        {
            if (pointer)
            {
                if(current == pointer->leftchild() ||current == pointer->rightchild()) //如果当前pointer的孩子就是current,返回parent
                    return pointer;
                aStack.push(pointer);               //当前结点地址入栈
                pointer = pointer->leftchild();     //当前链接结构指向左孩子
            }
            else                                    //左子树访问完毕,转向访问右子树
            {
                pointer = aStack.top();             //栈顶元素退栈
                aStack.pop();
                pointer = pointer->rightchild();    //当前链接结构指向右孩子
            }//endif
        } //endwhile
    }//endif
    return NULL;
}

template<class T>
BinaryTreeNode<T>* BinaryTree<T>::LeftSibling(BinaryTreeNode<T>* current)
{
    //返回current结点的左兄弟
    if(current)
    {
        BinaryTreeNode<T>* temp = Parent(current);    //返回current结点的父结点
        if ((temp == NULL) || current == temp->leftchild())
            return  NULL;      //如果父结点为空,或者current没有左兄弟,返回空
        else return temp->leftchild();
    }
    return NULL;
}

template<class T>
BinaryTreeNode<T>* BinaryTree<T>::RightSibling(BinaryTreeNode<T>* current)
{
    //返回current结点的右兄弟
    if(current)
    {
        BinaryTreeNode<T>* temp = Parent(current);  //返回current结点的父结点
        if(temp == NULL||current == temp->rightchild())
            return  NULL;                           //如果父结点为空,或者current没有右兄弟
        else return temp->rightchild();
    }
    return NULL;
}

template<class T>
void BinaryTree<T>:: CreateTree (const T& info, BinaryTree<T>& leftTree, BinaryTree<T>& rightTree)
{
    //由左子树leftTree、右子树rightTree和数据元素info创建一棵新树,根结点是info
    //其中this、leftTree、rightTree必须是不同的三棵树
    root = new BinaryTreeNode<T>(info, leftTree.root, rightTree.root);    //创建新树
    leftTree.root = rightTree.root = NULL;  //原来两棵子树的根结点指空,避免访问
}

template<class T>
void BinaryTree<T>:: DeleteBinaryTree(BinaryTreeNode<T>* root)    //以后序周游的方式删除二叉树
{
    if(root)
    {
        DeleteBinaryTree(root->left);           //递归删除左子树
        DeleteBinaryTree(root->right);          //递归删除右子树
        delete 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<T>:: PostOrder (BinaryTreeNode<T>* root)    //后序周游二叉树
{
    if(root != NULL)
    {
        PostOrder(root->leftchild());           //访问左子树
        PostOrder (root->rightchild());         //访问右子树
        Visit(root->value());                   //访问当前结点
    }
}

template<class T>
void BinaryTree<T>::PreOrderWithoutRecursion(BinaryTreeNode<T>* root)   //非递归前序周游二叉树或其子树
{
    using std::stack;                           //使用STL中的stack
    stack<BinaryTreeNode<T>* > aStack;
    BinaryTreeNode<T>* pointer = root;          //保存输入参数
    while(!aStack.empty() || pointer)
    {
        if (pointer)
        {
            Visit(pointer->value());            //访问当前结点
            aStack.push(pointer);               //当前结点地址入栈
            pointer = pointer->leftchild();     //当前链接结构指向左孩子
        }
        else                                    //左子树访问完毕,转向访问右子树
        {
            pointer = aStack.top();             //栈顶元素退栈
            aStack.pop();
            pointer = pointer->rightchild();    //当前链接结构指向右孩子
        }//endif
    } //endwhile
}

template<class T>
void BinaryTree<T>::InOrderWithoutRecursion(BinaryTreeNode<T>* root)
{
    //非递归中序周游二叉树或其子树
    using std::stack;                           //使用STL中的stack
    stack<BinaryTreeNode<T>* > aStack;
    BinaryTreeNode<T>* pointer = root;          //保存输入参数
    while(!aStack.empty() || pointer)
    {
        if (pointer)
        {
            aStack.push(pointer);               //当前结点地址入栈
            pointer = pointer->leftchild();     //当前链接结构指向左孩子
        }
        else                                    //左子树访问完毕,转向访问右子树
        {
            pointer = aStack.top();
            aStack.pop();                       //栈顶元素退栈
            Visit(pointer->value());            //访问当前结点
            pointer = pointer->rightchild();    //当前链接结构指向右孩子
        }
    } //endwhile
}

template<class T>
void BinaryTree<T>::PostOrderWithoutRecursion(BinaryTreeNode<T>* root)
{
    //非递归后序周游二叉树或其子树
    using std::stack;                       //使用STL栈部分
    StackElement<T> element;
    stack<StackElement<T > > aStack;        //栈申明
    BinaryTreeNode<T>* pointer;
    if(root == NULL)
        return;                             //空树即返回
    else pointer = root;                    //保存输入参数

    while (!aStack.empty() || pointer)
    {
        while (pointer != NULL)
        {
            element.pointer = pointer;
            element.tag = Left;
            aStack.push(element);
            pointer = pointer->leftchild(); //沿左子树方向向下周游
        }

        element = aStack.top();
        aStack.pop();                       //托出栈顶元素
        pointer = element.pointer;

        if (element.tag == Left)
        {
            //从左子树回来
            element.tag = Right;
            aStack.push(element);
            pointer = pointer->rightchild();
        }
        else                                //从右子树回来
        {
            Visit(pointer->value());        //访问当前结点
            pointer = NULL;
        }
    }
}

template<class T>
void BinaryTree<T>::LevelOrder(BinaryTreeNode<T>* root)
{
    //按层次周游二叉树或其子树
    using std::queue;                           //使用STL的队列
    queue<BinaryTreeNode<T>*> aQueue;
    BinaryTreeNode<T>* pointer = root;          //保存输入参数
    if (pointer)
        aQueue.push(pointer);                   //根结点入队列
    while (!aQueue.empty())                     //队列非空
    {
        pointer = aQueue.front();               //取队列首结点
        aQueue.pop();                           //当前结点出队列
        Visit(pointer->value());                //访问当前结点
        if(pointer->leftchild())
            aQueue.push(pointer->leftchild());  //左子树进队列
        if(pointer->rightchild())
            aQueue.push(pointer->rightchild()); //右子树进队列
    }
}

//****************  BinarySearchTree  *****************//
template <class T>
class BinarySearchTree:public BinaryTree<T>
{
public:
    BinarySearchTree()
    {
        this->root=NULL;
    };
    virtual ~BinarySearchTree() {};
    void Initialize(BinaryTreeNode<T> *newpointer);
    BinaryTreeNode<T>* Root()
    {
        return this->root;
    };

    void InsertNode(BinaryTreeNode<T>* root, BinaryTreeNode<T>* newpointer);
    void DeleteNode(BinaryTreeNode<T>* pointer);
    void DeleteNodeEx(BinaryTreeNode<T>* pointer);
};

//*********  implemention ***********//
template <class T>
void BinarySearchTree<T>::Initialize(BinaryTreeNode<T> *newpointer)
{
    this->root = newpointer;
}

template<class T>
void BinarySearchTree<T>::InsertNode(BinaryTreeNode<T>* root , BinaryTreeNode<T>* newpointer)                             //向二叉搜索树插入新结点
{
    BinaryTreeNode<T>* pointer = NULL;
    if(root == NULL)                    //如果是空树,初始化
    {
        Initialize(newpointer);	        //用指针newpointer初始化二叉搜索树树根,赋值实现
        return;
    }
    else
        pointer = root;
    while(1)
    {
        if (newpointer->value() == pointer->value())
            return ;					  //相等则不用插入
        else if (newpointer->value() < pointer->value())
        {
            if(pointer->leftchild() == NULL)
            {
                pointer->left = newpointer;		//作为左子树
                return;
            }
            else	pointer = pointer->leftchild();
        }
        else
        {
            if(pointer->rightchild() == NULL)
            {
                pointer->right = newpointer;      //作为右子树
                return;
            }
            else	pointer = pointer->rightchild();
        }
    }//endwhile
}

/*
template<class T>
void BinarySearchTree<T>::DeleteNode(BinaryTreeNode<T>* pointer)  {      //教材中写出这个算法
	//二叉搜索树中结点的删除
	BinaryTreeNode<T>* temppointer = NULL;
	if(!pointer)                            //如果删除的是空结点,则返回
		return;
	BinaryTreeNode<T>* parent = Parent(pointer);
	if (pointer->leftchild() == NULL)  {
		//被删结点无左子树,则将其右子树的根代替该删除结点
		if (parent == NULL)                 //被删除结点是根结点
			root = pointer->rightchild();
		else if (parent->leftchild() == pointer)
			parent->left = pointer->rightchild();
		else
			parent->right = pointer->rightchild();
		delete pointer;                     //删除该结点
		pointer = NULL;
		return;
	}
	else                                 //左子树不为空时
		temppointer = pointer->leftchild();
	while (temppointer->rightchild() != NULL)  //在左子树中找对称序的最后一个结点
		temppointer = temppointer->rightchild();
	//被删除结点的右子树作为temppointer的右子树
	temppointer->right = pointer->rightchild();
	//被删除结点的左子树根代替被删除结点
	if(NULL == parent)
		root = pointer->leftchild();
	else if (parent->leftchild() == pointer)
		parent->left = pointer->leftchild();
	else
		parent->right = pointer->leftchild();
	delete pointer;                          //删除该结点
	pointer = NULL;
	return;
}
*/

template <class T>
void BinarySearchTree<T>::DeleteNodeEx(BinaryTreeNode<T>* pointer)
/*思路:先独立出要替换的结点,然后替换删除的结点*/
{
    if ( pointer == NULL )                    // 若待删除结点不存在,返回
        return;
    BinaryTreeNode<T> * temppointer;          // 用于保存替换结点
    BinaryTreeNode<T> * tempparent = NULL;    // 用于保存替换结点的父结点
    BinaryTreeNode<T> * parent = this->Parent(pointer); // 保存删除结点的父结点
    // 如果待删除结点的左子树为空,就将它的右子树代替它
    if ( pointer->leftchild() == NULL )
        temppointer = pointer->rightchild();
    else
    {
        // 当待删除结点左子树不为空,就在左子树中寻找最大结点替换待删除结点
        temppointer = pointer->leftchild();
        while (temppointer->rightchild() != NULL )
        {
            tempparent = temppointer;
            temppointer = temppointer->rightchild();
        }
        // 删除替换结点
        if (tempparent == NULL)     // 如果没有右孩子
            pointer->left = temppointer->leftchild();
        else tempparent->right = temppointer->leftchild();  // 如果最大结点有一个左结点
        temppointer->left = pointer->leftchild();    // 继承pointer的左子树
        temppointer->right = pointer->rightchild();  // 继承pointer的右子树
    }
    // 用替换结点去替代真正的删除结点
    if (parent == NULL)
        this->root = temppointer;
    else if ( parent->leftchild() == pointer )
        parent->left = temppointer;
    else parent->right = temppointer;
    delete pointer;                         	// 删除该结点
    pointer = NULL;
    return;
}

#define N 11
int main()
{
    int K[N] = {50,19,35,55,20,5,100,52,88,53,92};        //建一棵图5.11所示的树
    BinarySearchTree<int> aBST;
    BinaryTreeNode<int > *newpointer, *node1, *node2;     // 循环插入结点

    for (int i = 0; i < N; i ++)
    {
        newpointer = new BinaryTreeNode<int>();
        newpointer->setValue(K[i]);
        aBST.InsertNode(aBST.Root(), newpointer);       //依次插入结点

        if (K[i] == 52)                                 //记录待删除结点的指针node1
        {
            node1 = newpointer;
            //	 cout<<node1->value()<<endl;
        }
        if (K[i] == 55)                                 //记录待删除结点的指针node2
            node2 = newpointer;
    }

    // 遍历结点
    cout << "Inorder sequence of the search tree:" << endl;
    aBST.InOrder(aBST.Root());  // 结果:5 19 20 35 50 52 53 55 88 92 100
    cout << endl;

    // 删除两个结点                          //教材中没讲这个算法
    //  cout << "删除结点52, 55." << endl;
    //	BST.DeleteNode(node1);
    //	aBST.DeleteNode(node2);

    // 删除两个结点的改进算法
    cout << "Delete the node: 52, 55." << endl;
    aBST.DeleteNodeEx(node1);
    aBST.DeleteNodeEx(node2);

    // 遍历节点
    cout << "Inorder sequence of the search tree after deleting the nodes:" << endl;
    aBST.InOrder(aBST.Root());  // 结果:5 19 20 35 50 53 88 92 100
    cout << endl;

    return 0;
}

相关文章推荐

二叉搜索树(C#,C++)

  • 2017-10-11 10:45
  • 3.58MB
  • 下载

二叉搜索树

  • 2016-05-23 15:57
  • 11KB
  • 下载

4-12 二叉搜索树的操作集

4-12 二叉搜索树的操作集 (30分) 本题要求实现给定二叉搜索树的5种常用操作。 函数接口定义: BinTree Insert( BinTree BST, ElementType...

二叉搜索树管理

二叉搜索树

之前看数据结构书的时候总喜欢跳过二叉树后面的部分(平衡二叉树),有点不敢去面对它(之前看着就犯困)! 但是逃避总不是办法吧!所以我决定去挑战一下这部分,也挑着一下自己吧,我决定去摸索一下二叉树后面的复...

二叉搜索树编程接口

二叉搜索树

  • 2017-01-18 16:59
  • 300KB
  • 下载

java实现二叉搜索树(BST)相关操作

java实现二叉搜索树(BST)相关操作,研究了了关于java的一些东西,欢迎讨论

二叉搜索树的插入

内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)