• C++ —— 二叉搜索树


    目录

    二叉搜索树概念

    二叉搜索树操作

    1. 二叉搜索树的查找

    2. 二叉搜索树的插入

    3. 二叉搜索树的删除 

    二叉搜索树的应用

    1. K模型

    2. KV模型

    二叉搜索树的性能分析

    二叉搜索树的实现(K&&KV)和测试(KV)


    C语言总结在这常见八大排序在这

    作者和朋友建立的社区:非科班转码社区-CSDN社区云💖💛💙

    期待hxd的支持哈🎉 🎉 🎉

    最后是打鸡血环节:你只管努力,剩下的交给天意🚀 🚀 🚀

    二叉搜索树概念

    二叉搜索树又称二叉排序树,它或者是一棵空树 ,或者是具有以下性质的二叉树 :
    1. 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
    2. 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
    3. 它的左右子树也分别为二叉搜索树

    二叉搜索树操作

     

    int a[] = {8, 3, 1, 10, 6, 4, 7, 14, 13};  

    1. 二叉搜索树的查找

    a 、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
    b 、最多查找高度次,走到到空,还没找到,这个值不存在。

    2. 二叉搜索树的插入

    插入的具体过程如下:
    a. 树为空,则直接新增节点,赋值给 root 指针
    b. 树不空,按二叉搜索树性质查找插入位置,插入新节点

    3. 二叉搜索树的删除 

    首先查找元素是否在二叉搜索树中,如果不存在,则返回 , 否则要删除的结点可能分下面四种情 况:
    a. 要删除的结点无孩子结点
    b. 要删除的结点只有左孩子结点
    c. 要删除的结点只有右孩子结点
    d. 要删除的结点有左、右孩子结点
    实际上a可以属于b或者c

    二叉搜索树的应用

    1. K模型

    K 模型即只有 key 作为关键码,结构中只需要存储 Key 即可,关键码即为需要搜索到 的值
    比如: 给一个单词 word ,判断该单词是否拼写正确 ,具体方式如下:
    以词库中所有单词集合中的每个单词作为 key ,构建一棵二叉搜索树。
    在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。

    2. KV模型

    每一个关键码 key ,都有与之对应的值 Value ,即 的键值对 。该种方式在现实生活中非常常见:
    比如 英汉词典就是英文与中文的对应关系 ,通过英文可以快速找到与其对应的中文,英
    文单词与其对应的中文 就构成一种键值对;
    再比如 统计单词次数 ,统计成功后,给定单词就可快速找到其出现的次数, 单词与其出
    现次数就是 就构成一种键值对。
    下面对于KV模型有对应的测试用例

    二叉搜索树的性能分析

    插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。
    对有 n 个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。
    但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:
    最优情况下,二叉搜索树为完全二叉树 ( 或者接近完全二叉树 ) ,其平均比较次数为: log2 N
    最差情况下,二叉搜索树退化为单支树 ( 或者类似单支 ) ,其平均比较次数为:N
    问题:如果退化成单支树,二叉搜索树的性能就失去了。那能否进行改进,不论按照什么次序插入关键码,二叉搜索树的性能都能达到最优?那么我们后续章节学习的AVL 红黑树就可以上场了。
    二叉搜索树也就是为了后面的AVL树和红黑树做铺垫!

    二叉搜索树的实现(K&&KV)和测试(KV)

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. #include
    4. using namespace std;
    5. /// //
    6. // K模型
    7. //template
    8. //struct BSTreeNode {
    9. // BSTreeNode(const K& key)
    10. // :_key(key)
    11. // , _left(nullptr)
    12. // , _right(nullptr)
    13. // {};
    14. //
    15. // BSTreeNode* _left;
    16. // BSTreeNode* _right;
    17. // K _key;
    18. //};
    19. //
    20. //template
    21. //class BSTree
    22. //{
    23. // typedef BSTreeNode Node;
    24. //public:
    25. // bool Insert(const K& key)
    26. // {
    27. // if (_root == nullptr)
    28. // {
    29. // _root = new Node(key);
    30. // return true;
    31. // }
    32. //
    33. // Node* parent = nullptr;
    34. // Node* cur = _root;
    35. // while (cur)
    36. // {
    37. // if (key > cur->_key)
    38. // {
    39. // parent = cur;
    40. // cur = cur->_right;
    41. // }
    42. // else if (key < cur->_key)
    43. // {
    44. // parent = cur;
    45. // cur = cur->_left;
    46. // }
    47. // else
    48. // {
    49. // return false;
    50. // }
    51. // }
    52. // cur = new Node(key);
    53. // //这里别用nullptr去判断,问就是写的时候好像不对
    54. // if (parent->_key > key)
    55. // {
    56. // parent->_left = cur;
    57. // }
    58. // else
    59. // {
    60. // parent->_right = cur;
    61. // }
    62. // return true;
    63. // }
    64. //
    65. // Node* Find(const K& key)
    66. // {
    67. // Node* cur = _root;
    68. // while (cur)
    69. // {
    70. // if (cur->_key > key)
    71. // {
    72. // cur = cur->_left;
    73. // }
    74. // else if (cur->_key < key)
    75. // {
    76. // cur = cur->_right;
    77. // }
    78. // else
    79. // {
    80. // return cur;
    81. // }
    82. // }
    83. // return false;
    84. // }
    85. //
    86. // //删除有三种情况
    87. // //要删除的孩子有左节点(1)
    88. // //要删除的孩子有右节点(2)
    89. // //要删除的孩子有左,右节点(3)替换法删除
    90. // //要删除的孩子无节点(属于1或2)
    91. // bool Erase(const K& key)
    92. // {
    93. // Node* cur = _root;
    94. // Node* parent = nullptr;
    95. // while (cur)
    96. // {
    97. // if (key < cur->_key)
    98. // {
    99. // parent = cur;
    100. // cur = cur->_left;
    101. // }
    102. // else if (key > cur->_right)
    103. // {
    104. // parent = cur;
    105. // cur = cur->_right;
    106. // }
    107. // else//找到了要删除的节点
    108. // {
    109. // // 一个孩子--左为空 or 右为空
    110. // // 两个孩子 -- 替换法
    111. // if (cur->_left == nullptr)
    112. // {
    113. // if (cur == _root)
    114. // {
    115. // _root = cur->_right;
    116. // }
    117. // else
    118. // {
    119. // if (cur == parent->_left)
    120. // {
    121. // parent->_left = cur->_right;
    122. // }
    123. // else
    124. // {
    125. // parent->_right = cur->_right;
    126. // }
    127. // }
    128. // delete cur;
    129. // }
    130. // else if (cur->_right == nullptr)
    131. // {
    132. // if (cur == _root)
    133. // {
    134. // _root = cur->_left;
    135. // }
    136. // else
    137. // {
    138. // if (cur == parent->_left)
    139. // {
    140. // parent->_left = cur->_left;
    141. // }
    142. // else
    143. // {
    144. // parent->_right = cur->_left;
    145. // }
    146. // }
    147. // delete cur;
    148. // }
    149. // else // 两个孩子都不为空,替换法删除
    150. // //找到左子树的最大节点或者右子树的最小节点替换
    151. // {
    152. // // 右子树的最小节点替代 且右子树最小节点,一定是左,右为空!
    153. // Node* minRight = cur->_right;
    154. // Node* minParent = cur;
    155. // while (minRight->_left)
    156. // {
    157. // minParent = minRight;
    158. // minRight = minRight->_left;
    159. // }
    160. //
    161. // std::swap(cur->_key, minRight->_key);
    162. // if (minParent->_right == minRight)
    163. // {
    164. // minParent->_right = minRight->_right;
    165. // }
    166. // else
    167. // {
    168. // minParent->_left = minRight->_right;
    169. // }
    170. // delete minRight;
    171. // }
    172. // return true;
    173. // }
    174. // }
    175. // return false;
    176. // }
    177. // void _InOrder(Node* root)
    178. // {
    179. // if (root == nullptr)
    180. // return;
    181. //
    182. // _InOrder(root->_left);
    183. // cout << root->_key << " ";
    184. // _InOrder(root->_right);
    185. // }
    186. // void InOrder()
    187. // {
    188. // _InOrder(_root);
    189. // }
    190. //private:
    191. // Node* _root = nullptr;
    192. //};
    193. //
    194. //int main()
    195. //{
    196. // BSTree bs;
    197. // bs.Insert(3);
    198. // bs.Insert(8);
    199. // bs.Insert(7);
    200. // bs.Insert(9);
    201. // bs.Insert(11);
    202. //
    203. // bs.InOrder();
    204. // return 0;
    205. //}
    206. /// //
    207. // K V模型
    208. template<class K,class V>
    209. struct BSTreeNode {
    210. BSTreeNode(const K& key,const V& value)
    211. :_key(key)
    212. ,_value(value)
    213. , _left(nullptr)
    214. , _right(nullptr)
    215. {};
    216. BSTreeNode* _left;
    217. BSTreeNode* _right;
    218. K _key;
    219. V _value;
    220. };
    221. template<class K,class V>
    222. class BSTree
    223. {
    224. typedef BSTreeNode Node;
    225. public:
    226. bool Insert(const K& key,const V& value)
    227. {
    228. if (_root == nullptr)
    229. {
    230. _root = new Node(key,value);
    231. return true;
    232. }
    233. Node* parent = nullptr;
    234. Node* cur = _root;
    235. while (cur)
    236. {
    237. if (key > cur->_key)
    238. {
    239. parent = cur;
    240. cur = cur->_right;
    241. }
    242. else if (key < cur->_key)
    243. {
    244. parent = cur;
    245. cur = cur->_left;
    246. }
    247. else
    248. {
    249. return false;
    250. }
    251. }
    252. cur = new Node(key, value);
    253. //这里别用nullptr去判断,问就是写的时候好像不对
    254. if (parent->_key > key)
    255. {
    256. parent->_left = cur;
    257. }
    258. else
    259. {
    260. parent->_right = cur;
    261. }
    262. return true;
    263. }
    264. Node* Find(const K& key)
    265. {
    266. Node* cur = _root;
    267. while (cur)
    268. {
    269. if (cur->_key > key)
    270. {
    271. cur = cur->_left;
    272. }
    273. else if (cur->_key < key)
    274. {
    275. cur = cur->_right;
    276. }
    277. else
    278. {
    279. return cur;
    280. }
    281. }
    282. return nullptr;
    283. }
    284. //删除有三种情况
    285. //要删除的孩子有左节点(1)
    286. //要删除的孩子有右节点(2)
    287. //要删除的孩子有左,右节点(3)替换法删除
    288. //要删除的孩子无节点(属于1或2)
    289. bool Erase(const K& key)
    290. {
    291. Node* cur = _root;
    292. Node* parent = nullptr;
    293. while (cur)
    294. {
    295. if (key < cur->_key)
    296. {
    297. parent = cur;
    298. cur = cur->_left;
    299. }
    300. else if (key > cur->_right)
    301. {
    302. parent = cur;
    303. cur = cur->_right;
    304. }
    305. else//找到了要删除的节点
    306. {
    307. // 一个孩子--左为空 or 右为空
    308. // 两个孩子 -- 替换法
    309. if (cur->_left == nullptr)
    310. {
    311. if (cur == _root)
    312. {
    313. _root = cur->_right;
    314. }
    315. else
    316. {
    317. if (cur == parent->_left)
    318. {
    319. parent->_left = cur->_right;
    320. }
    321. else
    322. {
    323. parent->_right = cur->_right;
    324. }
    325. }
    326. delete cur;
    327. }
    328. else if (cur->_right == nullptr)
    329. {
    330. if (cur == _root)
    331. {
    332. _root = cur->_left;
    333. }
    334. else
    335. {
    336. if (cur == parent->_left)
    337. {
    338. parent->_left = cur->_left;
    339. }
    340. else
    341. {
    342. parent->_right = cur->_left;
    343. }
    344. }
    345. delete cur;
    346. }
    347. else // 两个孩子都不为空,替换法删除
    348. //找到左子树的最大节点或者右子树的最小节点替换
    349. {
    350. // 右子树的最小节点替代 且右子树最小节点,一定是左,右为空!
    351. Node* minRight = cur->_right;
    352. Node* minParent = cur;
    353. while (minRight->_left)
    354. {
    355. minParent = minRight;
    356. minRight = minRight->_left;
    357. }
    358. std::swap(cur->_key, minRight->_key);
    359. if (minParent->_right == minRight)
    360. {
    361. minParent->_right = minRight->_right;
    362. }
    363. else
    364. {
    365. minParent->_left = minRight->_right;
    366. }
    367. delete minRight;
    368. }
    369. return true;
    370. }
    371. }
    372. return false;
    373. }
    374. void _InOrder(Node* root)
    375. {
    376. if (root == nullptr)
    377. return;
    378. _InOrder(root->_left);
    379. cout << root->_key << ": " << root->_value << endl;
    380. _InOrder(root->_right);
    381. }
    382. void InOrder()
    383. {
    384. _InOrder(_root);
    385. }
    386. private:
    387. Node* _root = nullptr;
    388. };
    389. void TestBSTree()
    390. {
    391. //BSTree dict;
    392. //dict.Insert("insert", "插入");
    393. //dict.Insert("erase", "删除");
    394. //dict.Insert("left", "左边");
    395. //dict.Insert("string", "字符串");
    396. //string str;
    397. //while (cin >> str)
    398. //{
    399. // auto ret = dict.Find(str);
    400. // if (ret)
    401. // {
    402. // cout << str << ":" << ret->_value << endl;
    403. // }
    404. // else
    405. // {
    406. // cout << "单词拼写错误" << endl;
    407. // }
    408. //}
    409. string strs[] = { "苹果", "西瓜", "苹果", "樱桃", "苹果", "樱桃", "苹果", "樱桃", "苹果" };
    410. // 统计水果出现的次
    411. BSTreeint> countTree;
    412. for (int i = 0; i < sizeof(strs) / sizeof(strs[0]); i++)
    413. {
    414. auto ret = countTree.Find(strs[i]);
    415. if (ret == nullptr)
    416. {
    417. countTree.Insert(strs[i], 1);
    418. }
    419. else
    420. {
    421. ret->_value++;
    422. }
    423. }
    424. countTree.InOrder();
    425. //for (auto str : strs)
    426. //{
    427. // auto ret = countTree.Find(str);
    428. // if (ret == NULL)
    429. // {
    430. // countTree.Insert(str, 1);
    431. // }
    432. // else
    433. // {
    434. // ret->_value++;
    435. // }
    436. //}
    437. //countTree.InOrder();
    438. }
    439. int main()
    440. {
    441. TestBSTree();
    442. return 0;
    443. }

    最后的最后,创作不易,希望读者三连支持💖

    赠人玫瑰,手有余香💖

  • 相关阅读:
    提前预警,防患未然:看千寻位置如何助力兴国县“跑赢”地质灾害
    java源码系列:HashMap源码验证,自己写的HashMap性能高吗?为什么在JDK8中新增红黑树?
    Python 框架学习 Django篇 (四) 数据库增删改查(CURD)
    games101-3 BRDF101
    解决在 Spring Boot 中运行 JUnit 测试遇到的 NoSuchMethodError 错误
    寄存器(内存访问)
    Linux:进程管理 | 进程创建 | 进程终止 | 进程等待 | 进程替换
    React Native中集成ArcGIS以显示地图、渲染自定义图层和获取地理信息数据
    react的different算法
    蓝桥等考Python组别十二级001
  • 原文地址:https://blog.csdn.net/weixin_62700590/article/details/126903752