• 数据结构与算法_二叉搜索树


    二叉搜索树可以说是二叉树的升级版,在数据的查找上,它优于普通二叉树。要让普通二叉树成为二叉搜索树,就要对于树中每个节点X,它左子树中所有节点元素的值小于X中的值,它右子树中所有节点元素的值大于X中的值。

    请看下边这两棵树,左边的树是一棵二叉搜索树,右边的树并不是二叉搜索树,因为7比6要大,而它却在6的左子树中。

    目录

    一、二叉搜索树的概念

    二、二叉搜索树操作

    查找

    插入

    删除

    三、二叉搜索树的代码实现

    四、二叉搜索树的应用

    key模型

    KV模型

    key模型和KV模型的实现:


    一、二叉搜索树的概念

    二叉搜索树又称二叉排序树,它可以是一棵空树......也可以是具有如下性质的二叉树

    若它的左子树不为空,则左子树上所有节点的值都小于根节点的值;

    若它的右子树不为空,则右子树上所有节点的值都大于根节点的值;

    它的左右子树也分别为二叉搜索树。

    二、二叉搜索树操作

    查找

    a、从根节点开始比较,查找,比根大则往右边走查找,比根小则往左边走查找;

    b、最多查找高度次,走到空还没找到,则这个值不存在。

    为什么说最多查找高度次?因为,如果二叉搜索树是下面这种形态,其实就趋近于链表了:

    插入

    a.数为空,则直接新增节点,赋值给root指针;

    b.树不为空,按二叉搜索树的性质查找插入位置,插入新节点。

    如下图,是依次插入16和0后的二叉搜索树:

    删除

    首先查找元素是否存在于二叉搜索树中。如果不存咋,就返回。如果存在,应该根据下面四种情况来删除:

    a.要删除的节点无孩子节点;

    b.要删除的节点只有左孩子节点;

    c.要删除的节点只有右孩子节点;

    d.要删除的节点有左、右孩子节点。

    看起来,有四种情况,事实上,a和b的情况可以放在一起考虑,那么删除过程如下:

    情况b:删除该节点且使被删除节点的双亲节点指向被删除节点的左孩子节点——直接删除

    情况c:删除该节点且使被删除节点的双亲节点指向被删除节点的右孩子节点——直接删除

    情况d:在它的右子树中寻找中序下的第一个节点(关键码最小),用它的值填补到被删除节点中,再来处理该节点的删除问题——替换法删除

    如下图,依次删除7、14、3、8

    7和14属于直接删除的场景

    3和8属于需要替换法进行删除的场景

    三、二叉搜索树的代码实现

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

    四、二叉搜索树的应用

    key模型

    K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值。

    比如:给一个单词word,判断该单词是否拼写正确,具体方式如下:

    以词库中所有单词集合中的每个单词作为key,构建一棵二叉搜索树;

    在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。 

    KV模型

    每一个关键码key,都有与之对应的值Value,即的键值对。该种方式在现实生活中非常常见:

    比如英汉词典就是英文与中文的对应关系,通过英文可以快速找到与其对应的中文,英文单词与对应的中文就构成一种键值对;

    再比如统计单词次数,统计成功后,给定单词就可快速找到其出现的次数,单词与其出现次数就是就构成一种键值对。

    key模型和KV模型的实现:

    1. namespace key
    2. {
    3. template<class K>
    4. struct BSTreeNode
    5. {
    6. BSTreeNode* _left;
    7. BSTreeNode* _right;
    8. K _key;
    9. BSTreeNode(const K& key)
    10. :_left(nullptr)
    11. , _right(nullptr)
    12. , _key(key)
    13. {}
    14. };
    15. template<class K>
    16. class BSTree
    17. {
    18. typedef BSTreeNode Node;
    19. public:
    20. BSTree()
    21. :_root(nullptr)
    22. {}
    23. BSTree(const BSTree& t)
    24. {
    25. _root = Copy(t._root);
    26. }
    27. BSTree& operator=(BSTree t)
    28. {
    29. swap(_root, t._root);
    30. return *this;
    31. }
    32. ~BSTree()
    33. {
    34. Destroy(_root);
    35. }
    36. bool Insert(const K& key)
    37. {
    38. if (_root == nullptr)
    39. {
    40. _root = new Node(key);
    41. return true;
    42. }
    43. Node* parent = nullptr;
    44. Node* cur = _root;
    45. while (cur)
    46. {
    47. if (cur->_key < key)
    48. {
    49. parent = cur;
    50. cur = cur->_right;
    51. }
    52. else if (cur->_key > key)
    53. {
    54. parent = cur;
    55. cur = cur->_left;
    56. }
    57. else
    58. {
    59. return false;
    60. }
    61. }
    62. cur = new Node(key);
    63. if (parent->_key < key)
    64. {
    65. parent->_right = cur;
    66. }
    67. else
    68. {
    69. parent->_left = cur;
    70. }
    71. return true;
    72. }
    73. bool Find(const K& key)
    74. {
    75. Node* cur = _root;
    76. while (cur)
    77. {
    78. if (cur->_key < key)
    79. {
    80. cur = cur->_right;
    81. }
    82. else if (cur->_key > key)
    83. {
    84. cur = cur->_left;
    85. }
    86. else
    87. {
    88. return true;
    89. }
    90. }
    91. return false;
    92. }
    93. bool Erase(const K& key)
    94. {
    95. Node* parent = nullptr;
    96. Node* cur = _root;
    97. while (cur)
    98. {
    99. if (cur->_key < key)
    100. {
    101. parent = cur;
    102. cur = cur->_right;
    103. }
    104. else if (cur->_key > key)
    105. {
    106. parent = cur;
    107. cur = cur->_left;
    108. }
    109. else
    110. {
    111. if (cur->_left == nullptr)
    112. {
    113. if (cur == _root)
    114. {
    115. _root = cur->_right;
    116. }
    117. else
    118. {
    119. if (parent->_right == cur)
    120. {
    121. parent->_right = cur->_right;
    122. }
    123. else
    124. {
    125. parent->_left = cur->_right;
    126. }
    127. }
    128. }
    129. else if (cur->_right == nullptr)
    130. {
    131. if (cur == _root)
    132. {
    133. _root = cur->_left;
    134. }
    135. else
    136. {
    137. if (parent->_right == cur)
    138. {
    139. parent->_right = cur->_left;
    140. }
    141. else
    142. {
    143. parent->_left = cur->_left;
    144. }
    145. }
    146. }
    147. else
    148. {
    149. Node* parent = cur;
    150. Node* leftMax = cur->_left;
    151. while (leftMax->_right)
    152. {
    153. parent = leftMax;
    154. leftMax = leftMax->_right;
    155. }
    156. swap(cur->_key, leftMax->_key);
    157. if (parent->_left == leftMax)
    158. {
    159. parent->_left = leftMax->_left;
    160. }
    161. else
    162. {
    163. parent->_right = leftMax->_left;
    164. }
    165. cur = leftMax;
    166. }
    167. delete cur;
    168. return true;
    169. }
    170. }
    171. return false;
    172. }
    173. void InOrder()
    174. {
    175. _InOrder(_root);
    176. cout << endl;
    177. }
    178. bool FindR(const K& key)
    179. {
    180. return _FindR(_root, key);
    181. }
    182. bool InsertR(const K& key)
    183. {
    184. return _InsertR(_root, key);
    185. }
    186. bool EraseR(const K& key)
    187. {
    188. return _EraseR(_root, key);
    189. }
    190. private:
    191. Node* Copy(Node* root)
    192. {
    193. if (root == nullptr)
    194. return nullptr;
    195. Node* copyroot = new Node(root->_key);
    196. copyroot->_left = Copy(root->_left);
    197. copyroot->_right = Copy(root->_right);
    198. return copyroot;
    199. }
    200. void Destroy(Node*& root)
    201. {
    202. if (root == nullptr)
    203. return;
    204. Destroy(root->_left);
    205. Destroy(root->_right);
    206. delete root;
    207. root = nullptr;
    208. }
    209. bool _EraseR(Node*& root, const K& key)
    210. {
    211. if (root == nullptr)
    212. return false;
    213. if (root->_key < key)
    214. {
    215. return _EraseR(root->_right, key);
    216. }
    217. else if (root->_key > key)
    218. {
    219. return _EraseR(root->_left, key);
    220. }
    221. else
    222. {
    223. Node* del = root;
    224. if (root->_left == nullptr)
    225. {
    226. root = root->_right;
    227. }
    228. else if (root->_right == nullptr)
    229. {
    230. root = root->_left;
    231. }
    232. else
    233. {
    234. Node* leftMax = root->_left;
    235. while (leftMax->_right)
    236. {
    237. leftMax = leftMax->_right;
    238. }
    239. swap(root->_key, leftMax->_key);
    240. return _EraseR(root->_left, key);
    241. }
    242. delete del;
    243. return true;
    244. }
    245. }
    246. bool _InsertR(Node*& root, const K& key)
    247. {
    248. if (root == nullptr)
    249. {
    250. root = new Node(key);
    251. return true;
    252. }
    253. if (root->_key < key)
    254. {
    255. return _InsertR(root->_right, key);
    256. }
    257. else if (root->_key > key)
    258. {
    259. return _InsertR(root->_left, key);
    260. }
    261. else
    262. {
    263. return false;
    264. }
    265. }
    266. bool _FindR(Node* root, const K& key)
    267. {
    268. if (root == nullptr)
    269. return false;
    270. if (root->_key < key)
    271. {
    272. return _FindR(root->_right, key);
    273. }
    274. else if (root->_key > key)
    275. {
    276. return _FindR(root->_left, key);
    277. }
    278. else
    279. {
    280. return true;
    281. }
    282. }
    283. void _InOrder(Node* root)
    284. {
    285. if (root == NULL)
    286. {
    287. return;
    288. }
    289. _InOrder(root->_left);
    290. cout << root->_key << " ";
    291. _InOrder(root->_right);
    292. }
    293. private:
    294. Node* _root;
    295. };
    296. namespace key_value
    297. {
    298. template<class K, class V>
    299. struct BSTreeNode
    300. {
    301. BSTreeNode* _left;
    302. BSTreeNode* _right;
    303. K _key;
    304. V _value;
    305. BSTreeNode(const K& key, const V& value)
    306. :_left(nullptr)
    307. , _right(nullptr)
    308. , _key(key)
    309. , _value(value)
    310. {}
    311. };
    312. template<class K, class V>
    313. class BSTree
    314. {
    315. typedef BSTreeNode Node;
    316. public:
    317. BSTree()
    318. :_root(nullptr)
    319. {}
    320. void InOrder()
    321. {
    322. _InOrder(_root);
    323. cout << endl;
    324. }
    325. Node* FindR(const K& key)
    326. {
    327. return _FindR(_root, key);
    328. }
    329. bool InsertR(const K& key, const V& value)
    330. {
    331. return _InsertR(_root, key, value);
    332. }
    333. bool EraseR(const K& key)
    334. {
    335. return _EraseR(_root, key);
    336. }
    337. private:
    338. bool _EraseR(Node*& root, const K& key)
    339. {
    340. if (root == nullptr)
    341. return false;
    342. if (root->_key < key)
    343. {
    344. return _EraseR(root->_right, key);
    345. }
    346. else if (root->_key > key)
    347. {
    348. return _EraseR(root->_left, key);
    349. }
    350. else
    351. {
    352. Node* del = root;
    353. if (root->_left == nullptr)
    354. {
    355. root = root->_right;
    356. }
    357. else if (root->_right == nullptr)
    358. {
    359. root = root->_left;
    360. }
    361. else
    362. {
    363. Node* leftMax = root->_left;
    364. while (leftMax->_right)
    365. {
    366. leftMax = leftMax->_right;
    367. }
    368. swap(root->_key, leftMax->_key);
    369. return _EraseR(root->_left, key);
    370. }
    371. delete del;
    372. return true;
    373. }
    374. }
    375. bool _InsertR(Node*& root, const K& key, const V& value)
    376. {
    377. if (root == nullptr)
    378. {
    379. root = new Node(key, value);
    380. return true;
    381. }
    382. if (root->_key < key)
    383. {
    384. return _InsertR(root->_right, key, value);
    385. }
    386. else if (root->_key > key)
    387. {
    388. return _InsertR(root->_left, key, value);
    389. }
    390. else
    391. {
    392. return false;
    393. }
    394. }
    395. Node* _FindR(Node* root, const K& key)
    396. {
    397. if (root == nullptr)
    398. return nullptr;
    399. if (root->_key < key)
    400. {
    401. return _FindR(root->_right, key);
    402. }
    403. else if (root->_key > key)
    404. {
    405. return _FindR(root->_left, key);
    406. }
    407. else
    408. {
    409. return root;
    410. }
    411. }
    412. void _InOrder(Node* root)
    413. {
    414. if (root == NULL)
    415. {
    416. return;
    417. }
    418. _InOrder(root->_left);
    419. cout << root->_key << ":" << root->_value << endl;
    420. _InOrder(root->_right);
    421. }
    422. private:
    423. Node* _root;
    424. };

  • 相关阅读:
    朔雪流量复制器的前端
    雷达编程实战之静态杂波滤除与到达角估计
    CAT1 4G+以太网开发板腾讯云手机微信小程序显示温度和下发控制
    R语言爬虫代码模版:技术原理与实践应用
    网络编程进化史:Netty Channel 的崭新篇章
    我可能永远也没办法成为全栈工程师了,看看你还差多少?
    【N年测试总结】 测试入职一家新公司的工作开展思路
    xss反射型漏洞复现
    Hive的时间操作函数
    java之线程间通信
  • 原文地址:https://blog.csdn.net/m0_60464690/article/details/133420205