二叉查找树

详细相关性质 可查看维基百科"二叉查找树"

关键性质:1 设root为二叉查找树的结点

               如果a是root的任意左结点   key[a] < key[root]

               如果a是root的任意右结点   key[root] < key[a]

              2 没有关键值相等的节点,中序遍历二叉查找树可得到一个关键字的有序序列

下述实现基于上面的图(丑了点,但不影响阅读,有向父节点与子节点关系清晰)

 #include <iostream>
 #include <crtdbg.h>
 using namespace std;
 /*二叉查找树*/
 /*实现中假设关键元素互不相同*/
 typedef int DataType;
 
 struct TreeNode
 {
     TreeNode()
     {
        right = NULL;
        left  = NULL;
     }
     DataType data;
     TreeNode *right;
     TreeNode *left;
};

struct BiTree
{
    TreeNode *root;

    BiTree()
    {
        root=NULL;
    }
    ~BiTree()
    {
        Destroy(root);
        root = NULL;
    }
    void Destroy(TreeNode *p)
    {
        if (p == NULL) return;

        Destroy(p->left);
        Destroy(p->right);
        delete p;
    }
    /*先确定父结点位置,在确定子节点位置*/
    bool Insert(const DataType &data)
    {
         TreeNode *pNew = new TreeNode;
         pNew->data = data;
         pNew->left = NULL;
         pNew->right = NULL;

        //TreeNode **p = &root;(可通过二级指针简化代码,但可读性较差)
        //while( (*p) != NULL)
        //{
        // if (data == (*p)->data )
        //     return false;
        // else if (data < (*p)->data)
        //     p = &( (*p)->left);
        // else
        //     p = &( (*p)->right);
        //}
        //*p = pNew;
        //return true;

        TreeNode *p = root;
        TreeNode *temp = NULL;
        while(p != NULL)
        {
            temp = p;
            if (data == p->data )
                return false;
            else if (data < p->data)
                p = p->left;
            else
                p = p->right;
        }
        if (temp == NULL)
            root = pNew;
        else
            (data < temp->data) ? (temp->left = pNew) : (temp->right = pNew);
        return true;
    }
    //寻找关键字为data的节点,若找到删除返回true,否则返回false
    bool Delete(const DataType &data)
    {
        TreeNode *p = root;
        while(p != NULL)
        {
            if (data == p->data )
            {
                Delete(p);
                return true;
            }
            else if (data < p->data)
                p = p->left;
            else
                p = p->right;

        }
        return false;
    }

    /*考虑3种情况,要删除的结点有两子节点,只有一个子节点,没有子节点*/
    void Delete(TreeNode *p)                
    {
        TreeNode *temp;
        TreeNode *parent = NULL;
        if (p->left == NULL && p->right == NULL)//左右子树都空
        {
            parent = GetParent(root, p);
            (parent->left->data == p->data)? (parent->left = NULL) : (parent->right = NULL);
            delete p;
            p = NULL;
        }
        else if (p->right == NULL)//右子树为空
        {
            temp = p->left;
            p->data = p->left->data;
            p->left = temp->left;
            p->right = temp->right;
            delete temp;
            temp = NULL;
        }
        else if (p->left == NULL)//左子树为空
        {
            temp = p->right;
            p->data = p->right->data;
            p->left = temp->left;
            p->right = temp->right;
            delete temp;
            temp = NULL;
        }
        else//左右子树都不为空
        {
            temp = TreePre(p);//寻找p的前驱,进行替换,然后删除前驱节点
            if (temp != NULL)
            {
                p->data = temp->data;

                parent = GetParent(root, temp);
                (parent->left->data == temp->data)? (parent->left = NULL) : (parent->right = NULL);
                delete temp;
                temp = NULL;
            }
        }
    }
     /*非线性结构转换成线性结构(内存是线性的) 有3种方法 先序 中序 后序*/
     /*中序遍历*/
     void InOrderTree(TreeNode *p)
     {
         if (p == NULL) return ;
         
         InOrderTree(p->left);
         cout << p->data << endl;
         InOrderTree(p->right);
     }
     /*递归版本*/
     TreeNode* Search(TreeNode *p, DataType key)
     {
         if (p == NULL || p->data == key)
             return p;
 
         if (key < p->data)
         {
             return Search(p->left, key);
         }
         else
         {
             return Search(p->right, key);
         }
     }
     /*非递归版本*/
     TreeNode* Find(DataType key)
     {
         TreeNode *p = root;
         while(p != NULL && p->data != key)
         {
             if (key < p->data)
             {
                 p = p->left;
             }
             else
             {
                 p = p->right;
             }
         }
         return p;
     }
     /*寻找最小值*/
     TreeNode* Minimum(TreeNode *p)
     {
         TreeNode *pTemp = p;
         while(pTemp != NULL)
         {
             p = pTemp;
             pTemp = p->left;
         }
         return p;
     }
     /*寻找最大值*/
     TreeNode* Maximum(TreeNode *p)
     {
         TreeNode *pTemp = p;
         while(pTemp != NULL)
         {
             p = pTemp;
             pTemp = p->right;
         }
         return p;
     }
     /*获取父节点*/
     /*此处为递归,也可以是尾递归,利用栈作为辅助的数据结构,具体实现可查看 普通树的第7点*/
     TreeNode * GetParent(TreeNode *parent, TreeNode *p)
     {
         if (parent == NULL || parent == p)
             return NULL;
         if (parent->left == p || parent->right == p)
         {
             return parent;
         }
         TreeNode *ret = GetParent(parent->left, p);
         if(ret)
             return ret;
         return GetParent(parent->right, p);
     }
     /*寻找前趋(关键字都不相同) x的前趋为小于key[x]的 最大关键值
       考虑两种情况
       1 如果结点x的左子树非空,则x的前趋为左子树中的最右结点
       2 如果结点x的左子树为空,则x的前趋为x的祖先结点,且x的只能为其父结点的右子结点    
    */
     TreeNode *TreePre(TreeNode *p)
     {
         if (p->left)
         {
             return Maximum(p->left);
         }
         TreeNode *parent = GetParent(root,p);
         while(parent != NULL && p == parent->left)
         {
             p = parent;
             parent = GetParent(root,parent);
         }
         return parent;
     }
     /*寻找后继(关键字都不相同) x的后继为大于key[x]的 最小关键值
       考虑两种情况 
       1 如果结点x的右子树非空,则x的后继为右子树中的最左结点
       2 如果结点x的右子树为空,则x的后继为x的祖先结点,且x的只能为其父结点的左子结点          
     */
     TreeNode *TreeAfter(TreeNode *p)
     {
         if (p->right)
         {
             return Minimum(p->right);
         }
         TreeNode *parent = GetParent(root,p);
         while(parent != NULL && p == parent->right)
         {
             p = parent;
             parent = GetParent(root,parent);
         }
         return parent;
     }
 };
 void main()
 {
     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
 
     BiTree biTree;
     /*测试插入*/
     biTree.Insert(15);
     biTree.Insert(6);
     biTree.Insert(3);
     biTree.Insert(7);
     biTree.Insert(2);
     biTree.Insert(4);
     biTree.Insert(13);
     biTree.Insert(9);
     biTree.Insert(18);
     biTree.Insert(17);
     biTree.Insert(20);
     biTree.InOrderTree(biTree.root);
 
     /*测试最大最小*/
     cout << endl;
     TreeNode * p = NULL;
     p = biTree.Maximum(biTree.root);
     cout << p->data << endl;
     p = biTree.Minimum(biTree.root);
     cout << p->data << endl;
 
     /*测试两种find 以及获取父节点GetParent*/
     cout <<endl;
     TreeNode *p2 = NULL;
     p = biTree.Find(17);
     if (p != NULL)
     {
         p2 = biTree.GetParent(biTree.root, p);
         cout << p2->data << endl;
     }
     p = biTree.Search(biTree.root, 20);
     if (p != NULL)
     {
         cout << biTree.GetParent(biTree.root, p)->data << endl;
     }
 
     /*测试 9前趋、 13后继*/
     cout <<endl;
     TreeNode *p3 = NULL;
     p3 = biTree.TreePre(biTree.Find(9));
     if ( p3 != NULL)
     {
         cout << p3->data << endl;
     }
     p3 = biTree.TreeAfter(biTree.Find(13));
     if ( p3 != NULL)
     {
         cout << p3->data << endl;
     }
     
     ///*测试 删除 3中情况*/
     //cout <<endl;
     biTree.Delete(6);    /*有两结点*/
     //biTree.Delete(13);  /*只有一个子节点*/
     //biTree.Delete(20);  /*没有子节点*/
     biTree.InOrderTree(biTree.root);
 
     system("pause");
 }

 

@2015, 4-18 优化Insert/Delete函数实现 添加关键性质

posted on 2014-05-09 23:05  Seven++  阅读(216)  评论(0编辑  收藏  举报

导航