二叉排序树

二叉树中使用最广泛的就是搜索二叉树;
搜索二叉树还有其它名称:二叉排序树、二叉查找树等;
 
1.搜索二叉树的优点
1】有很好的查询性能                        
2】有很好的新增和删除的性能                        
3】若左子树不空,则左子树上所有结点的值均小于它的根结点的值                        
4】若右子树不空,则右子树上所有结点的值均大于它的根结点的值                        
5】左、右子树也分别为二叉排序树    
 
如图:典型的搜索二叉树
对搜索二叉树进行中序遍历的结果就是元素从小到大排序后的结果;
如果二叉树中的元素是基本类型int、short等,可以直接操作;
如果元素是对象,那么该对象的类必须重载运算符><==,因为搜索二叉树就是通过这些运算符来排序的;
搜索二叉树里面不允许有重复元素;
 
2.搜索二叉树的操作
1)新增元素
例如:在上图的搜索二叉树中新增节点8
    比较8和15,因为8<15,所以应该放左子树,如果左子树的节点没值就直接写到这里,有值就要继续比较;
    比较8和5,8>5,放右子树;
    8<12,放左边;
    8<10,放左边;
    8>6,放右边;
    8>7,放右边,7的右子树是空的,因此8放这里;
    因此8应该放在以7为父节点的右子树中;    
 
例如:新增18
    经过一系列查找,树中原本有一个18;
    因为搜索二叉树中不允许重复元素,因此直接返回;
 
2)查找元素
例如:从上面图的二叉树中找6
    6<15,从左找;
    6>5,往右找;
    6<12,往左找;
    6<10,往左找,然后找到了;
 
例如:找21
    21>15,从右找;
    21>20,往右找;
    21<23,往左找,然后左边没有了,因此找不到返回空;
    
3)删除元素
情况一:叶子节点        
1】删除该节点        
2】将父节点(左或者右)指针置NULL   
例如:删除3,直接删除3,然后5的左指针指向NULL;     
        
情况2:只有一个子树        
1】删除该节点        
2】将父节点(左或者右)指针指向子树   
例如:删除6,直接删除6,然后将10的左指针指向7;     
        
情况3:左右子树都有    
方法1)    
    1】用右子树最小的节点取代源节点        
    2】再递归删除最小节点   
例如:删除5
    先从5的右边找到最小的6;
    不删除5而是将节点处的值从5换为6;
    再删除原来的6;
原理:
    右边最小的数一定比根节点大,也比左边任何一个数大;
    右边最小的数只可能是叶子节点,或只有右子树,删除操作简单;
方法2)
    1】用左子树最大的节点取代源节点 
    2】删除最大节点
 
3.搜索二叉树的实现
头文件:
#ifndef SEARCHTREE_H
#define SEARCHTREE_H
 
#include "stdio.h"
#include "stdlib.h"
#include "windows.h"
 
#define SUCCESS                         1 // 执行成功                    
#define FAIL             -1 // 执行失败                             
                                
template<class T>                                
class TreeNode{                                
public:                                
    T element;                    //当前节点存储的数据        
    TreeNode<T>* pLeft;                    //指向左子节点的指针        
    TreeNode<T>* pRight;                    //指向右子节点的指针        
    TreeNode<T>* pParent;                    //指向父结点的指针        
                                
    TreeNode(T& ele){                            
        //初始化Node节点                        
        memset(&element,0,sizeof(TreeNode));                        
        //为元素赋值                        
        memcpy(&element,&ele,sizeof(T));                        
        pLeft = pRight = pParent = NULL;                        
    }                            
    //重载== 比较两结点是否相等                            
    bool operator==(TreeNode<T>* node){                             
        return node->element == element?true:false;                        
    }                            
};                                
                                
template<class T>                                
class BSortTree{                                
public:                                
    BSortTree();                        //构造函数    
    ~BSortTree();                        //析构函数    
public:                            //判断树是否为空    
    bool IsEmpty();                        //新增节点    
    DWORD Insert(T element);                        //删除节点    
    void Delete(T element);                            
    TreeNode<T>* Search(T element);                        //查找节点    
    void InOrderTraverse(TreeNode<T>* pNode);                        //中序遍历    
    void PreOrderTraverse(TreeNode<T>* pNode);                        //前序遍历    
    void PostOrderTraverse(TreeNode<T>* pNode);                        //后序遍历    
private:                                
    TreeNode<T>* GetMaxNode(TreeNode<T>* pNode);                        //获取以pNode为根的最大节点    
    TreeNode<T>* GetMinNode(TreeNode<T>* pNode);                        //获取以pNode为根的最小节点    
    TreeNode<T>* SearchNode(TreeNode<T>* pNode,T element);                        //获取以pNode为根的最小节点    
    DWORD InsertNode(T element, TreeNode<T>* pNode);                        //新增节点    
    TreeNode<T>* DeleteNode(T element, TreeNode<T>* pNode);                        //删除节点    
    void Clear(TreeNode<T>* pNode);                        //清空所有节点    
private:                                
    TreeNode<T>* m_pRoot;                        //根结点指针    
    int size;                        //树中元素总个数    
};                                
                                
template<class T>                                 
BSortTree<T>::BSortTree()                                
{                                
    m_pRoot = NULL;                            
    size = 0;                            
}                                
template<class T>                                 
BSortTree<T>::~BSortTree(){                                
                                
    Clear(m_pRoot);                            
}                                
template<class T>                                 
DWORD BSortTree<T>::Insert(T element)                                
{                                
    //如果根节点为空                            
    if ( !m_pRoot )                            
    {                            
        m_pRoot = new TreeNode<T>(element);                        
        size++;                        
        return SUCCESS;                        
    }                            
    //如果根节点不为空                            
    return InsertNode(element, m_pRoot);                            
}                                
template<class T>                                 
DWORD BSortTree<T>::InsertNode(T element, TreeNode<T>* pNode)                                
{                                
    //将元素封装到节点中                            
    TreeNode<T>* pNewNode = new TreeNode<T>(element);                            
    //如果element == 当前节点 直接返回                            
    if(element == pNode->element)                            
    {                            
        return SUCCESS;                        
    }                            
    //如果pNode的左子节点为NULL 并且element < 当前节点                            
    if(pNode->pLeft == NULL && element < pNode->element)                            
    {                            
        pNode->pLeft = pNewNode;                        
        pNewNode->pParent = pNode;                        
        size++;                        
        return SUCCESS;                        
    }                            
    //如果pNode的右子节点为NULL 并且element > 当前节点                            
    if(pNode->pRight == NULL && element > pNode->element){                            
        pNode->pRight = pNewNode;                        
        pNewNode->pParent = pNode;                        
        size++;                        
        return SUCCESS;                        
    }                            
    //如果element<当前节点 且当前节点的左子树不为空                            
    if(element < pNode->element)                            
    {                            
        InsertNode(element,pNode->pLeft);                        
    }                            
    else                            
    {                            
        InsertNode(element,pNode->pRight);                        
    }                            
    return SUCCESS;                            
}                                
                                
template<class T>                                 
void BSortTree<T>::Clear(TreeNode<T>* pNode)                                
{                                
    if(pNode!=NULL)                            
    {                            
        Clear(pNode->pLeft);                        
        Clear(pNode->pRight);                        
        delete pNode;                        
        pNode=NULL;                        
    }                            
}                                
                                
template<class T>                                 
bool BSortTree<T>::IsEmpty()                                
{                                
    return size==0?true:false;                            
}                                
                                
template<class T>                                 
TreeNode<T>* BSortTree<T>::Search(T element)                                
{                                
    return SearchNode(m_pRoot, element);                            
}                                
template<class T>                                 
TreeNode<T>* BSortTree<T>::SearchNode(TreeNode<T>* pNode,T element)                                
{                                
    if(pNode == NULL)                    //如果节点为NULL        
    {                            
        return NULL;                        
    }                            
    else if(element == pNode->element)                    //如果相等        
    {                            
        return pNode;                        
    }                    //如果比节点的元素小 向左找        
    else if(element < pNode->element)                            
    {                            
        return SearchNode(pNode->pLeft,element);                        
    }                            
    else                    //如果比节点的元素大 向右找        
    {                            
        return SearchNode(pNode->pRight,element);                        
    }                            
}                                
                                
template<class T>                                 
void BSortTree<T>::Delete(T element)                                
{                                
    //先找到元素所在节点
    TreeNode<T>* node = Search(element);    
    if(node == NULL){    //如果没有该元素则直接返回
        return;    
    }
 
    TreeNode<T>* parent = node->pParent;
 
    if(!node->pLeft && !node->pRight){    //如果是叶子节点直接删除
            if(parent->pLeft == node){    //判断是父节点的左子树还是右子树
                parent->pLeft = NULL;
            }else{
                parent->pRight = NULL;
            }
            delete node;
    }else if(!node->pLeft){    //如果只有一个子树,删除该节点并用子树代替该节点
            if(parent->pLeft == node){    //判断是父节点的左子树还是右子树
                parent->pLeft = node->pRight;
            }else{
                parent->pRight = node->pRight;
            }
        node->pRight->pParent = parent;
        delete node;
    }else if(!node->pRight){
            if(parent->pLeft == node){    //判断是父节点的左子树还是右子树
                parent->pLeft = node->pLeft;
            }else{
                parent->pRight = node->pLeft;
            }
        node->pLeft->pParent = parent;
        delete node;
    }else{    //如果目标节点左右子树都不为空
        TreeNode<T>* min = node->pRight;
        while(min->pLeft){
            min = min->pLeft;    //找到目标节点右子树中最小的元素
        }
        memcpy(node, min, sizeof(T));    //用右子树最小元素的值替换目标节点的值
 
        TreeNode<T>* minParent = min->pParent;    //删除最小元素
        if(minParent->pLeft == min){    
            minParent->pLeft = min->pRight;    
        }else{
            minParent->pRight = min->pRight;
        }
        if(min->pRight){
            min->pRight->pParent = minParent;
        }
        delete min;
    }
 
    size--;
    return;
}                                    
 
//中序遍历
template<class T>
void BSortTree<T>::InOrderTraverse(TreeNode<T>* pNode){
    if(pNode){
        InOrderTraverse(pNode->pLeft);
        printf("%d\t",pNode->element);
        InOrderTraverse(pNode->pRight);
    }
}                        
                                
#endif                                

 

测试:
#include "SearchTree.h"                            
                                                        
void fun()                                
{                                
    //12 8 5 9 17 15 13    
    /*                    
                12        
                        
        8                17
                        
    5        9        15    
                        
                13        
                    
    */                    
 
    BSortTree<int> tree;                            
    
    //插入
    tree.Insert(12);                            
    tree.Insert(8);                            
    tree.Insert(5);                            
    tree.Insert(9);                            
    tree.Insert(17);                            
    tree.Insert(15);                            
    tree.Insert(13);                            
    
    //查找特定元素
    TreeNode<int>* p = tree.Search(9);                                                            
    printf("%x %d\n",p,p->element);    
    
    //中序遍历
    tree.InOrderTraverse(tree.Search(12));
    printf("\n");
 
 
    //删除元素8
    tree.Delete(8);
    tree.InOrderTraverse(tree.Search(12));
    printf("\n");
}                                
 
void main(){
    
    fun();
    getchar();
}

 

结果:
 
 
 
posted @ 2019-12-06 08:36  L丶银甲闪闪  阅读(308)  评论(0编辑  收藏  举报