• 二叉查找树


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

    关键性质: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函数实现 添加关键性质

  • 相关阅读:
    插入排序
    选择排序
    P1338 末日的传说 逆序数对
    P1582倒水 位运算
    P2158 [SDOI2008] (欧拉函数
    HDU 6274 二分+预处理(CCPC K题
    P1219 N皇后
    [USACO1.5] 回文质数
    Codeforces #123D: 后缀数组+单调栈
    单调栈 单调队列
  • 原文地址:https://www.cnblogs.com/sevenPP/p/3715292.html
Copyright © 2020-2023  润新知