• 二叉树进阶


    目录

    前言

    二叉搜索树(非递归)

    二叉搜索树(递归)

    二叉树的性能分析

    Key模型与Key-Value模型

    全部代码


    前言

    二叉搜索树又称二叉排序树,它或者是一棵空树,因为它的左子树的值<根的值<右子树的值(左右子树不为空时),左右子树也是二叉搜索树,所以它的中序遍历则是升序

    节点封装如下

    注意:为了避免存储重复数,以及找不到要删除的数的节点,插入与删除的返回类型采用布尔类型

    二叉搜索树具有排序+去重的作用

    二叉搜素树的实现(非递归)

    插入

    如果是一颗空树,则直接插入即可

    要插入节点,需要找到前驱节点,所以一般都需要遍历这颗树,就需要两个指针parent和cur,类似于单链表插入节点

    新插入节点的值与二叉树中某个节点的值一致时,则直接返回,即插入失败

    找到前驱节点之后,再判断节点值的大小,来确定插入左边还是右边,然后返回即可

     

    删除

    先查找要删除的元素

    找到之后,要删除的元素只有右节点,或者左右节点均为空时,如果只有根节点,就删除根节点,否则就删除找到的节点,然后让它的父亲指向它的右孩子

    找到之后,要删除的元素只有左节点,或者左右节点均为空时,如果只有根节点,就删除根节点,否则就删除找到的节点,然后让它的父亲指向它的左孩子

     

    找到之后,左右孩子都存在时,先找到右子树的最左节点,然后把找到节点的值赋值给要删除的节点,如果找到的最左节点,有右孩子时,则让它的父亲指向它的右孩子,然后删除刚刚找到的左节点或右节点

    二叉搜索树的实现(递归)

    因为节点指针是私有的,而递归写法的插入与删除都要用到根节点,所以需要再套一层

     

    插入

    递归和非递归类似,都是先找到其前驱节点,然后再连接即可,比如下图,开始值为3的节点的右孩子是nullptr,然后再展开后,将指向nullptr的指针指向值为5的节点,则值为3的节点的右孩子是值为5的节点了

    删除

    和非递归类似,都是先找到要删除的节点,如果要删除的节点为不存在,则删除失败

    要删除的节点的右孩子为nullptr时,让它的左孩子变为它的父节点的左孩子即可

     要删除的节点的左孩子为nullptr时,让它的右孩子变为它的父节点的左孩子即可

    要删除的节点既有左孩子又有右孩子时,先将要删除的节点的值与根节点的右子树的最左节点的值交换,然后遍历根节点的右子树来删除最左节点

    二叉树的性能分析

    最优情况:当二叉搜索树是完全二叉树时,其平均比较次数为log2 n

    最差情况:当二叉搜索树退化为单支树时,其平均比较次数为n/2

    解决方法

    将二叉树进一步优化,使其成为平衡二叉树,有AVL树或红黑树两种

    Key模型与Key-Value模型

    Key模型

    门禁系统,存储该栋楼所有同学学号或小区所有业主的车牌号,有就让进入,没有就无法进入

    Key—Value模型

    字典,通过一个单词的英文,从而知道它的中文意思

    Key—Value模型则需要存储两个值,一个是Key,另一个则是Value

     

    全部代码

    1. //二叉搜索树
    2. #pragma once
    3. #include<iostream>
    4. using namespace std;
    5. template<class K>
    6. struct BSTreeNode
    7. {
    8. BSTreeNode<K>* _left;
    9. BSTreeNode<K>* _right;
    10. K _key;
    11. BSTreeNode(const K& key):_left(nullptr),_right(nullptr),_key(key)
    12. {}
    13. };
    14. template<class K>
    15. struct BSTree
    16. {
    17. typedef BSTreeNode<K> Node;
    18. public:
    19. BSTree():_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. //找到,准备开始删除
    97. if (cur->_left == nullptr)
    98. {
    99. if (parent == nullptr)
    100. {
    101. _root = cur->_right;
    102. }
    103. else
    104. {
    105. if (parent->_left == cur)
    106. parent->_left = cur->_right;
    107. else
    108. parent->_right = cur->_right;
    109. }
    110. delete cur;
    111. }
    112. else if (cur->_right == nullptr)
    113. {
    114. if (parent == nullptr)
    115. {
    116. _root = cur->_left;
    117. }
    118. else
    119. {
    120. if (parent->_left == cur)
    121. parent->_left = cur->_left;
    122. else
    123. parent->_right = cur->_left;
    124. }
    125. delete cur;
    126. }
    127. else
    128. {
    129. Node* minParent = cur;
    130. Node* min = cur->_right;
    131. while (min->_left)
    132. {
    133. minParent = min;
    134. min = min->_left;
    135. }
    136. cur->_key = min->_key;
    137. if (minParent->_left == min)
    138. minParent->_left = min->_right;
    139. else
    140. minParent->_right = min->_right;
    141. delete min;
    142. }
    143. return true;
    144. }
    145. }
    146. return false;
    147. }
    148. bool InsertR(const K& key)
    149. {
    150. return _InsertR(_root, key);
    151. }
    152. Node* FindR(const K& key)
    153. {
    154. return _FindR(_root, key);
    155. }
    156. Node* EraseR(const K& key)
    157. {
    158. return _Erase(_root, key);
    159. }
    160. void InOrder()
    161. {
    162. _InOrder(_root);
    163. cout << endl;
    164. }
    165. private:
    166. bool _EraseR(Node*& root, const K& key)
    167. {
    168. if (root == nullptr)
    169. return false;
    170. if (root->_key < key)
    171. {
    172. return _EraseR(root->_right, key);
    173. }
    174. else if(root->_key > key)
    175. {
    176. return _EraseR(root->_left, key);
    177. }
    178. else
    179. {
    180. Node* del = root;
    181. if (root->_left == nullptr)
    182. {
    183. root = root->_right;
    184. }
    185. else if (root->_right == nullptr)
    186. {
    187. root = root->_left;
    188. }
    189. else
    190. {
    191. Node* min = root->_right;
    192. while (min->_left)
    193. {
    194. min = min->_left;
    195. }
    196. swap(min->_key, root->_key);
    197. //递归到右子树去删除
    198. return _EraseR(root->_right, key);
    199. }
    200. delete del;
    201. return true;
    202. }
    203. }
    204. bool _InsertR(Node*& root, const K& key)
    205. {
    206. if (root == nullptr)
    207. {
    208. root = new Node(key);
    209. return true;
    210. }
    211. if (root->_key < key)
    212. return _InsertR(root->_right, key);
    213. else if (root->_key > key)
    214. return _InsertR(root->_left, key);
    215. else
    216. return false;
    217. }
    218. Node* _FindR(Node* root,const K& key)
    219. {
    220. if (_root == nullptr)
    221. {
    222. return nullptr;
    223. }
    224. if (root->_key < key)
    225. {
    226. return _FindR(root->_right, key);
    227. }
    228. else if (root->_key > key)
    229. {
    230. return _FindR(root->_left, key);
    231. }
    232. else
    233. {
    234. return root;
    235. }
    236. }
    237. void _InOrder(Node* root)
    238. {
    239. if (root == nullptr)
    240. {
    241. return;
    242. }
    243. _InOrder(root->_left);
    244. cout << root->_key << " ";
    245. _InOrder(root->_right);
    246. }
    247. private:
    248. Node* _root;
    249. };
    250. void TestBSTree()
    251. {
    252. BSTree<int> t;
    253. int a[] = { 5,3,4,1,7,8,2,6,0,9,5,5 };
    254. for (auto e : a)
    255. {
    256. t.InsertR(e);
    257. }
    258. //排序+去重
    259. t.InOrder();
    260. t.Erase(7);
    261. t.InOrder();
    262. t.Erase(5);
    263. t.InOrder();
    264. t.Erase(0);
    265. t.InOrder();
    266. t.Erase(1);
    267. t.InOrder();
    268. for (auto e : a)
    269. {
    270. t.Erase(e);
    271. t.InOrder();
    272. }
    273. t.InOrder();
    274. }
    275. namespace KV
    276. {
    277. template<class K,class V>
    278. struct BSTreeNode
    279. {
    280. BSTreeNode<K,V>* _left;
    281. BSTreeNode<K,V>* _right;
    282. K _key;
    283. V _value;
    284. //pair<K,V> _kv;
    285. BSTreeNode(const K& key,const V& value) :_left(nullptr), _right(nullptr), _key(key),_value(value)
    286. {}
    287. };
    288. template<class K,class V>
    289. struct BSTree
    290. {
    291. typedef BSTreeNode<K, V> Node;
    292. public:
    293. BSTree() :_root(nullptr)
    294. {}
    295. bool Insert(const K& key, const V& value)
    296. {
    297. if (_root == nullptr)
    298. {
    299. _root = new Node(key, value);
    300. return true;
    301. }
    302. Node* parent = nullptr;
    303. Node* cur = _root;
    304. while (cur)
    305. {
    306. if (cur->_key < key)
    307. {
    308. parent = cur;
    309. cur = cur->_right;
    310. }
    311. else if (cur->_key > key)
    312. {
    313. parent = cur;
    314. cur = cur->_left;
    315. }
    316. else
    317. {
    318. return false;
    319. }
    320. }
    321. cur = new Node(key, value);
    322. if (parent->_key < key)
    323. {
    324. parent->_right = cur;
    325. }
    326. else
    327. {
    328. parent->_left = cur;
    329. }
    330. return true;
    331. }
    332. Node* Find(const K& key)
    333. {
    334. Node* cur = _root;
    335. while (cur)
    336. {
    337. if (cur->_key < key)
    338. {
    339. cur = cur->_right;
    340. }
    341. else if (cur->_key > key)
    342. {
    343. cur = cur->_left;
    344. }
    345. else
    346. {
    347. return cur;
    348. }
    349. }
    350. return nullptr;
    351. }
    352. bool Erase(const K& key)
    353. {
    354. Node* parent = nullptr;
    355. Node* cur = _root;
    356. while (cur)
    357. {
    358. if (cur->_key < key)
    359. {
    360. parent = cur;
    361. cur = cur->_right;
    362. }
    363. else if (cur->_key > key)
    364. {
    365. parent = cur;
    366. cur = cur->_left;
    367. }
    368. else
    369. {
    370. //找到,准备开始删除
    371. if (cur->_left == nullptr)
    372. {
    373. if (parent == nullptr)
    374. {
    375. _root = cur->_right;
    376. }
    377. else
    378. {
    379. if (parent->_left == cur)
    380. parent->_left = cur->_right;
    381. else
    382. parent->_right = cur->_right;
    383. }
    384. delete cur;
    385. }
    386. else if (cur->_right == nullptr)
    387. {
    388. if (parent == nullptr)
    389. {
    390. _root = cur->_left;
    391. }
    392. else
    393. {
    394. if (parent->_left == cur)
    395. parent->_left = cur->_left;
    396. else
    397. parent->_right = cur->_left;
    398. }
    399. delete cur;
    400. }
    401. else
    402. {
    403. Node* minParent = cur;
    404. Node* min = cur->_right;
    405. while (min->_left)
    406. {
    407. minParent = min;
    408. min = min->_left;
    409. }
    410. cur->_key = min->_key;
    411. if (minParent->_left == min)
    412. minParent->_left = min->_right;
    413. else
    414. minParent->_right = min->_right;
    415. delete min;
    416. }
    417. return true;
    418. }
    419. }
    420. return false;
    421. }
    422. void InOrder()
    423. {
    424. _InOrder(_root);
    425. cout << endl;
    426. }
    427. private:
    428. void _InOrder(Node* root)
    429. {
    430. if (root == nullptr)
    431. {
    432. return;
    433. }
    434. _InOrder(root->_left);
    435. cout << root->_key << ":" << root->_value << endl;
    436. _InOrder(root->_right);
    437. }
    438. Node* _root;
    439. };
    440. void TestBstree1()
    441. {
    442. //字典KV模型
    443. BSTree<string, string> dict;
    444. dict.Insert("sort", "排序");
    445. dict.Insert("left", "左边");
    446. dict.Insert("right", "右边");
    447. dict.Insert("map", "地图、映射");
    448. //...
    449. string str;
    450. while (cin >> str)
    451. {
    452. BSTreeNode<string, string>* ret = dict.Find(str);
    453. if (ret)
    454. {
    455. cout << "对应中文解释: " << ret->_value << endl;
    456. }
    457. else
    458. {
    459. cout << "无此单词" << endl;
    460. }
    461. }
    462. }
    463. void TestBstree2()
    464. {
    465. //统计水果出现次数
    466. string arr[] = { "苹果" , "西瓜" ,"草莓" , "苹果", "西瓜" , "苹果" , "苹果" , "西瓜" ,"苹果","香蕉" ,"苹果" , "香蕉" };
    467. BSTree<string, int> countTree;
    468. for (auto& str : arr)
    469. {
    470. //BSTreeNode<string,int>* ret = cout << countTree.Find(str);
    471. auto ret = countTree.Find(str);
    472. if (ret != nullptr)
    473. {
    474. ret->_value++;
    475. }
    476. else
    477. {
    478. countTree.Insert(str, 1);
    479. }
    480. }
    481. countTree.InOrder();
    482. }
    483. }

     

  • 相关阅读:
    函数栈详解
    JDK锁优化
    记一次 .NET 某娱乐聊天流平台 CPU 爆高分析
    48页数字政府智慧政务一网通办解决方案
    决策单调性优化dp
    八、QOS队列调度与报文丢弃
    3分钟:腾讯云免费SSL证书申请教程_免费HTTPS证书50张
    MySQL之MHA高可用配置及故障
    【设计模式】【第五章】【开具增值税发票】【建造者模式 + 原型模式】
    JavaScript从入门到精通系列第二十三篇:JavaScript中的数组
  • 原文地址:https://blog.csdn.net/weixin_58867976/article/details/125409765