C++(进阶) 第3章 二叉搜索树

打印 上一主题 下一主题

主题 828|帖子 828|积分 2484

C++(进阶) 第3章 二叉搜索树


  

前言

之前在数据布局篇简朴的介绍了二叉搜索树,本篇博客会具体的介绍

一、什么是二叉搜索树?

⼆叉搜索树的概念

⼆叉搜索树⼜称⼆叉排序树,它或者是⼀棵空树,或者是具有以下性质的⼆叉树:
• 若它的左⼦树不为空,则左⼦树上全部结点的值都⼩于等于根结点的值
• 若它的右⼦树不为空,则右⼦树上全部结点的值都⼤于等于根结点的值
• 它的左右⼦树也分别为⼆叉搜索树

下面就是一颗比力经典的二叉搜索树

搜索二叉树也叫排序二叉树,由于它走中序遍历的时候刚好就是有序的

二、搜索二叉树的实现

0.搜索二叉树的时间复杂度

搜索二叉树的做好环境下时间复杂度就是log N,但是会出现极端环境

以是时间复杂度就是N
但是后面会有AVL树,红黑树,可以优化差不多 log N

1.根本框架

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. template<class K>
  4. struct BSTreeNode
  5. {
  6.         K _key;
  7.         BSTreeNode<K>* _left;
  8.         BSTreeNode<K>* _right;
  9.         BSTreeNode(const K& key)
  10.                 :_key(key)
  11.                 ,_left(nullptr)
  12.                 ,_right(nullptr)
  13.         {
  14.         }
  15. };
  16. template<class K>
  17. class BSTree
  18. {
  19.         typedef BSTreeNode<K> Node;
  20. public:
  21. private:
  22.         Node* _root = nullptr;
  23. };
复制代码

2.Find

普通的二叉树其实没有什么意义,如果只是普通的二叉树它存东西的效率其实还不如链表,以是在原来的二叉树基础上添加了一些规则,左孩子比根小,右孩子比根大
如果就用下面的例子,现在我要在这颗树里面搜索看看有没有16这个数字

如果我们查找的值比根大那么就可以直接往右走,比根小只必要往左走就可以了那么最多只必要找这棵树的高度次就可以了
如果找到null了那么就阐明找不到
  1. bool Find(const K& key)
  2. {
  3.         Node* cur = _root;
  4.         while (cur)
  5.         {
  6.                 if (cur->_key < key)
  7.                 {
  8.                         cur = cur->_right;
  9.                 }
  10.                 else if(cur->_key > key)
  11.                 {
  12.                         cur = cur->_left;
  13.                 }
  14.                 else
  15.                 {
  16.                         return true;
  17.                 }
  18.         }
  19.         return false;
  20. }
复制代码

3.Insert

注意:这里有一个规定,树里面的数据是不允许重复的,也,如果树里面已经有了10,那么这里就不允许再次插入,以是这里insert返回值用bool
  1. bool Insert(const K& key)
  2. {
  3.         if (_root == nullptr)
  4.         {
  5.                 _root = new Node(key);
  6.                 return true;
  7.         }
  8.         Node* cur = _root;
  9.         Node* parent = nullptr;
  10.         while (cur)
  11.         {
  12.                 if (cur->_key < key)
  13.                 {
  14.                         parent = cur;
  15.                         cur = cur->_right;
  16.                        
  17.                 }
  18.                 else if (cur->_key > key)
  19.                 {
  20.                         parent = cur;
  21.                         cur = cur->_left;
  22.                        
  23.                 }
  24.                 else
  25.                 {
  26.                         return false;
  27.                 }
  28.         }
  29.         cur = new Node(key);
  30.         if (parent->_key < cur->_key)
  31.         {
  32.                 parent->_right = cur;
  33.         }
  34.         else
  35.         {
  36.                 parent->_left= cur;
  37.         }
  38.         return true;
  39. }
复制代码

4.InOder

这里我用的是子函数的情势由于如果不这样的话,外面调用就要传入参数(_root)但是这里我_root是保护调用不了,
  1.         void InOder()
  2.         {
  3.                 _InOder(_root);
  4.         }
  5. private:
  6.         void _InOder(Node* root)
  7.         {
  8.                 if (root == nullptr)
  9.                 {
  10.                         return;
  11.                 }
  12.                 _InOder(root->_left);
  13.                 cout << root->_key << ' ';
  14.                 _InOder(root->_right);
  15.         }
复制代码

写完中序遍历就可以看下程序有没有写错了

这里可以看到输出的是有序的,就阐明这里是没有写错的
到这里的完备代码就长这样
  1. #pragma once#include<bits/stdc++.h>using namespace std;template<class K>struct BSTreeNode{        K _key;        BSTreeNode<K>* _left;        BSTreeNode<K>* _right;        BSTreeNode(const K& key)                :_key(key)                ,_left(nullptr)                ,_right(nullptr)        {        }};template<class K>class BSTree{        typedef BSTreeNode<K> Node;public:        bool Find(const K& key)        {                Node* cur = _root;                while (cur)                {                        if (cur->_key < key)                        {                                cur = cur->_right;                        }                        else if(cur->_key > key)                        {                                cur = cur->_left;                        }                        else                        {                                return true;                        }                }                return false;        }        bool Insert(const K& key)        {                if (_root == nullptr)                {                        _root = new Node(key);                        return true;                }                Node* cur = _root;                Node* parent = nullptr;                while (cur)                {                        if (cur->_key < key)                        {                                parent = cur;                                cur = cur->_right;                                                        }                        else if (cur->_key > key)                        {                                parent = cur;                                cur = cur->_left;                                                        }                        else                        {                                return false;                        }                }                cur = new Node(key);                if (parent->_key < cur->_key)                {                        parent->_right = cur;                }                else                {                        parent->_left= cur;                }                return true;        }        void InOder(Node* root)        {                if (root == nullptr)                {                        return;                }                InOder(root->_left);                cout << root->_key << ' ';                InOder(root->_right);        }        void InOder()
  2.         {
  3.                 _InOder(_root);
  4.         }
  5. private:
  6.         void _InOder(Node* root)
  7.         {
  8.                 if (root == nullptr)
  9.                 {
  10.                         return;
  11.                 }
  12.                 _InOder(root->_left);
  13.                 cout << root->_key << ' ';
  14.                 _InOder(root->_right);
  15.         }
  16. private:        Node* _root = nullptr;};
复制代码
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include"bstree.h"
  3. int main()
  4. {
  5.     int arr[] = { 8,3,1,10,6,4,7,14,13 };
  6.     BSTree<int> t;
  7.     for (auto e : arr)
  8.     {
  9.         t.Insert(e);
  10.     }
  11.     t.InOder();
  12.     return 0;
  13. }
复制代码

5.Erase

这里删除的话就比力复杂了,必要先找到要删的谁人节点,然后删除,但是删除的谁人节点大概会还有孩子并且删除了以后搜索二叉树不能乱,大致可以分成以下三种环境

  • 没有孩子
  • 只要一个孩子
  • 有俩个孩子

如果这里我要删除3,那么我必要找到一个人替换3的位置,这个时候左子树最右边的节点,或者右子树最左边的节点都可以,以是上面的1,2种环境可以归类成一种环境,由于最左边或者最左边的一定是只有一个孩子或者没有孩子的环境
如果上面我要删掉3,那么我去找右子树的最左边的值也就是4,那么3替换成4,然后下面的4就可以直接删掉了
  1. bool Erase(const K& key)
  2. {
  3.         Node* cur = _root;
  4.         Node* parent = nullptr;
  5.         while (cur)
  6.         {
  7.                 if (cur->_key < key)
  8.                 {
  9.                         parent = cur;
  10.                         cur = cur->_right;
  11.                 }
  12.                 else if (cur->_key > key)
  13.                 {
  14.                         parent = cur;
  15.                         cur = cur->_left;
  16.                 }
  17.                 else
  18.                 {
  19.                         if (cur->_left == nullptr)
  20.                         {
  21.                                 if (parent == nullptr)
  22.                                 {
  23.                                         _root = cur->_right;
  24.                                 }
  25.                                 else
  26.                                 {
  27.                                         if (parent->_left == cur)
  28.                                         {
  29.                                                 parent->_left = cur->_right;
  30.                                         }
  31.                                         else
  32.                                         {
  33.                                                 parent->_right = cur->_right;
  34.                                         }
  35.                                 }
  36.                                
  37.                                 delete cur;
  38.                                 return true;
  39.                         }
  40.                         else if(cur->_right == nullptr)
  41.                         {
  42.                                 if (parent == nullptr)
  43.                                 {
  44.                                         _root = cur->_left;
  45.                                 }
  46.                                 else
  47.                                 {
  48.                                         if (parent->_left == cur)
  49.                                         {
  50.                                                 parent->_left = cur->_left;
  51.                                         }
  52.                                         else
  53.                                         {
  54.                                                 parent->_right = cur->_left;
  55.                                         }
  56.                                 }
  57.                                
  58.                                 delete cur;
  59.                                 return true;
  60.                         }
  61.                         else
  62.                         {
  63.                                 Node* RightMin = cur->_right;
  64.                                 Node* RightMinP = cur;
  65.                                 while (RightMin ->_left)
  66.                                 {
  67.                                         RightMinP = RightMin;
  68.                                         RightMin = RightMin->_left;
  69.                                 }
  70.                                 cur->_key = RightMin->_key;
  71.                                 if (RightMinP->_left == RightMin )
  72.                                 {
  73.                                         RightMinP->_left = RightMin->_right;
  74.                                 }
  75.                                 else
  76.                                 {
  77.                                         RightMinP->_right = RightMin->_right;
  78.                                 }
  79.                                
  80.                                 delete RightMin;
  81.                                 return true;
  82.                         }
  83.                 }
  84.         }
  85.         return false;
  86. }
复制代码


三 、完备代码

  1. #pragma once
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. template<class K>
  5. struct BSTreeNode
  6. {
  7.         K _key;
  8.         BSTreeNode<K>* _left;
  9.         BSTreeNode<K>* _right;
  10.         BSTreeNode(const K& key)
  11.                 :_key(key)
  12.                 ,_left(nullptr)
  13.                 ,_right(nullptr)
  14.         {
  15.         }
  16. };
  17. template<class K>
  18. class BSTree
  19. {
  20.         typedef BSTreeNode<K> Node;
  21. public:
  22.         bool Find(const K& key)
  23.         {
  24.                 Node* cur = _root;
  25.                 while (cur)
  26.                 {
  27.                         if (cur->_key < key)
  28.                         {
  29.                                 cur = cur->_right;
  30.                         }
  31.                         else if (cur->_key > key)
  32.                         {
  33.                                 cur = cur->_left;
  34.                         }
  35.                         else
  36.                         {
  37.                                 return true;
  38.                         }
  39.                 }
  40.                 return false;
  41.         }
  42.         bool Insert(const K& key)
  43.         {
  44.                 if (_root == nullptr)
  45.                 {
  46.                         _root = new Node(key);
  47.                         return true;
  48.                 }
  49.                 Node* cur = _root;
  50.                 Node* parent = nullptr;
  51.                 while (cur)
  52.                 {
  53.                         if (cur->_key < key)
  54.                         {
  55.                                 parent = cur;
  56.                                 cur = cur->_right;
  57.                         }
  58.                         else if (cur->_key > key)
  59.                         {
  60.                                 parent = cur;
  61.                                 cur = cur->_left;
  62.                         }
  63.                         else
  64.                         {
  65.                                 return false;
  66.                         }
  67.                 }
  68.                 cur = new Node(key);
  69.                 if (parent->_key < cur->_key)
  70.                 {
  71.                         parent->_right = cur;
  72.                 }
  73.                 else
  74.                 {
  75.                         parent->_left = cur;
  76.                 }
  77.                 return true;
  78.         }
  79.         void InOrder()
  80.         {
  81.                 _InOrder(_root);
  82.                 cout << endl;
  83.         }
  84.         bool Erase(const K& key)
  85.         {
  86.                 Node* cur = _root;
  87.                 Node* parent = nullptr;
  88.                 while (cur)
  89.                 {
  90.                         if (cur->_key < key)
  91.                         {
  92.                                 parent = cur;
  93.                                 cur = cur->_right;
  94.                         }
  95.                         else if (cur->_key > key)
  96.                         {
  97.                                 parent = cur;
  98.                                 cur = cur->_left;
  99.                         }
  100.                         else
  101.                         {
  102.                                 if (cur->_left == nullptr)
  103.                                 {
  104.                                         if (parent == nullptr)
  105.                                         {
  106.                                                 _root = cur->_right;
  107.                                         }
  108.                                         else
  109.                                         {
  110.                                                 if (parent->_left == cur)
  111.                                                 {
  112.                                                         parent->_left = cur->_right;
  113.                                                 }
  114.                                                 else
  115.                                                 {
  116.                                                         parent->_right = cur->_right;
  117.                                                 }
  118.                                         }
  119.                                        
  120.                                         delete cur;
  121.                                         return true;
  122.                                 }
  123.                                 else if(cur->_right == nullptr)
  124.                                 {
  125.                                         if (parent == nullptr)
  126.                                         {
  127.                                                 _root = cur->_left;
  128.                                         }
  129.                                         else
  130.                                         {
  131.                                                 if (parent->_left == cur)
  132.                                                 {
  133.                                                         parent->_left = cur->_left;
  134.                                                 }
  135.                                                 else
  136.                                                 {
  137.                                                         parent->_right = cur->_left;
  138.                                                 }
  139.                                         }
  140.                                        
  141.                                         delete cur;
  142.                                         return true;
  143.                                 }
  144.                                 else
  145.                                 {
  146.                                         Node* RightMin = cur->_right;
  147.                                         Node* RightMinP = cur;
  148.                                         while (RightMin ->_left)
  149.                                         {
  150.                                                 RightMinP = RightMin;
  151.                                                 RightMin = RightMin->_left;
  152.                                         }
  153.                                         cur->_key = RightMin->_key;
  154.                                         if (RightMinP->_left == RightMin )
  155.                                         {
  156.                                                 RightMinP->_left = RightMin->_right;
  157.                                         }
  158.                                         else
  159.                                         {
  160.                                                 RightMinP->_right = RightMin->_right;
  161.                                         }
  162.                                        
  163.                                         delete RightMin;
  164.                                         return true;
  165.                                 }
  166.                         }
  167.                 }
  168.                 return false;
  169.         }
  170. private:
  171.         void _InOrder(Node* root)
  172.         {
  173.                 if (root == nullptr)
  174.                 {
  175.                         return;
  176.                 }
  177.                 _InOrder(root->_left);
  178.                 cout << root->_key << ' ';
  179.                 _InOrder(root->_right);       
  180.         }
  181. private:
  182.        
  183.         Node* _root = nullptr;
  184. };
复制代码

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include"BStree.h"
  3. using namespace std;
  4. int main()
  5. {
  6.     int arr[] = { 8,3,1,10,6,4,7,14,13 };
  7.     BSTree<int> t;
  8.     for (auto e : arr)
  9.     {
  10.         t.Insert(e);
  11.     }
  12.     t.Insert(16);
  13.     t.Insert(4);
  14.     t.InOrder();
  15.     for (auto e : arr)
  16.     {
  17.         t.Erase(e);
  18.         t.InOrder();
  19.     }
  20.     return 0;
  21. }
复制代码
总结

删除有点复杂照旧要花时间去明白

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

干翻全岛蛙蛙

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表