用于存放学校的作业便于复习。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
6.9 KiB

  1. //
  2. // Created by 423A35C7 on 2023-12-15.
  3. //
  4. // 09:19
  5. // 20:06
  6. #include <algorithm>
  7. #include <cassert>
  8. #include <functional>
  9. #include <iostream>
  10. #include <memory>
  11. #include <vector>
  12. template<typename T>
  13. class BiSortNode {
  14. public:
  15. using NodePtr = std::unique_ptr<BiSortNode>;
  16. // 好像这里没法使用initializer_list,initializer_list是对于多个相同值的初始化,而不是一个东西的初始化参数列表
  17. template<typename... Args>
  18. explicit BiSortNode(Args... args, std::function<bool(T, T)> _compare) : data(args...) {
  19. this->compare_function_(_compare);
  20. }
  21. template<typename... Args>
  22. explicit BiSortNode(Args... args) : data(args...) {
  23. this->compare_function_ = [](T&a, T&b) { return a < b; };
  24. }
  25. void update_depth_and_balance_factor() {
  26. const int left_depth = this->left_child ? this->left_child->depth + 1 : 0;
  27. const int right_depth = this->right_child ? this->right_child->depth + 1 : 0;
  28. this->balance_factor = left_depth - right_depth;
  29. this->depth = std::max(left_depth, right_depth);
  30. }
  31. // 这里的左旋指的是LL型需要进行的旋转,名称不一定对
  32. // 这部分用注释不好解释,建议最好搜一下网上的图解,理解了之后再看这部分代码
  33. static void left_rotate(NodePtr&unbalanced) {
  34. NodePtr pivot = std::move(unbalanced->left_child);
  35. unbalanced->left_child = std::move(pivot->right_child);
  36. pivot->right_child = std::move(unbalanced);
  37. unbalanced = std::move(pivot);
  38. unbalanced->update_depth_and_balance_factor();
  39. unbalanced->right_child->update_depth_and_balance_factor();
  40. }
  41. // 这里的右旋指的是RR型需要进行的旋转,名称不一定对
  42. // 这部分用注释不好解释,建议最好搜一下网上的图解,理解了之后再看这部分代码
  43. static void right_rotate(NodePtr&unbalanced) {
  44. NodePtr pivot = std::move(unbalanced->right_child);
  45. unbalanced->right_child = std::move(pivot->left_child);
  46. pivot->left_child = std::move(unbalanced);
  47. unbalanced = std::move(pivot);
  48. unbalanced->update_depth_and_balance_factor();
  49. unbalanced->left_child->update_depth_and_balance_factor();
  50. }
  51. static void insert(NodePtr&current_node, T new_data) {
  52. // int balance_diff = 0;
  53. if (new_data < current_node->data) {
  54. // 如果新的节点比当前节点小就找它的左子树
  55. if (current_node->left_child == nullptr) {
  56. current_node->left_child = std::make_unique<BiSortNode>(new_data);
  57. }
  58. else {
  59. current_node->insert(current_node->left_child, new_data);
  60. }
  61. }
  62. else {
  63. // 否则找右子树
  64. if (current_node->right_child == nullptr) {
  65. current_node->right_child = std::make_unique<BiSortNode>(new_data);
  66. }
  67. else {
  68. current_node->insert(current_node->right_child, new_data);
  69. }
  70. }
  71. current_node->update_depth_and_balance_factor();
  72. if (current_node->balance_factor > 1) {
  73. // 左子树比右子树高
  74. assert(current_node->left_child->balance_factor != 0); // 此时左子树的平衡因子不应为0
  75. if (current_node->left_child->balance_factor < 0) // 符合LR型
  76. current_node->right_rotate(current_node->left_child); // 先进行右旋(逆时针),转化为LL
  77. current_node->left_rotate(current_node); // 左旋(顺时针)
  78. }
  79. else if (current_node->balance_factor < -1) {
  80. // 右子树比左子树高
  81. assert(current_node->right_child->balance_factor != 0); // 此时右子树的平衡因子不应为0
  82. if (current_node->right_child->balance_factor > 0) // 符合RL型
  83. current_node->left_rotate(current_node->right_child); // 先进行左旋(顺时针),转化为RR型
  84. current_node->right_rotate(current_node); // 右旋(逆时针)
  85. }
  86. // current_node->balance_factor += balance_diff;
  87. current_node->update_depth_and_balance_factor();
  88. // return balance_diff;
  89. }
  90. void inorder_traversal(std::vector<T>&output) {
  91. if (this->left_child != nullptr) this->left_child->inorder_traversal(output);
  92. output.push_back(this->data);
  93. if (this->right_child != nullptr) this->right_child->inorder_traversal(output);
  94. }
  95. void preorder_traversal(std::vector<T>&output) {
  96. output.push_back(this->data);
  97. if (this->left_child != nullptr) this->left_child->preorder_traversal(output);
  98. if (this->right_child != nullptr) this->right_child->preorder_traversal(output);
  99. }
  100. void postorder_traversal(std::vector<T>&output) {
  101. if (this->left_child != nullptr) this->left_child->postorder_traversal(output);
  102. if (this->right_child != nullptr) this->right_child->postorder_traversal(output);
  103. output.push_back(this->data);
  104. }
  105. void traverse_and_output(std::ostream&out, std::function<void(std::vector<T>&)> traverse_function) {
  106. std::vector<T> traverse_result;
  107. traverse_function(traverse_result);
  108. for (auto const&i: traverse_result)
  109. std::cout << i << " ";
  110. std::cout << std::endl;
  111. }
  112. private:
  113. NodePtr left_child;
  114. NodePtr right_child;
  115. int balance_factor = 0; // 平衡因子
  116. int depth = 0; // 树的深度(高度)
  117. T data;
  118. std::function<bool(T&, T&)> compare_function_;
  119. };
  120. int main() {
  121. std::vector<int> origin_vector;
  122. int temp;
  123. while (std::cin >> temp) {
  124. origin_vector.push_back(temp);
  125. }
  126. auto generator = origin_vector.cbegin();
  127. BiSortNode<int>::NodePtr bi_sort_node{new BiSortNode<int>(*generator++)};
  128. while (generator != origin_vector.cend()) {
  129. bi_sort_node->insert(bi_sort_node, *generator++);
  130. }
  131. std::vector<int> traversal_result;
  132. bi_sort_node->inorder_traversal(traversal_result);
  133. std::cout << "为了便于验证,以下依次输出平衡二叉树的前序、中序、后序遍历结果:" << std::endl;
  134. bi_sort_node->traverse_and_output(std::cout, [&bi_sort_node](std::vector<int>&output) {
  135. bi_sort_node->preorder_traversal(output);
  136. });
  137. bi_sort_node->traverse_and_output(std::cout, [&bi_sort_node](std::vector<int>&output) {
  138. bi_sort_node->inorder_traversal(output);
  139. });
  140. bi_sort_node->traverse_and_output(std::cout, [&bi_sort_node](std::vector<int>&output) {
  141. bi_sort_node->postorder_traversal(output);
  142. });
  143. return 0;
  144. }
  145. // 输入:
  146. // 98 77 94 67 59 60 56 68 95 98 32 39 32 17 5 5 8 19 40 41
  147. // 输出:
  148. // 为了便于验证,以下依次输出平衡二叉树的前序、中序、后序遍历结果:
  149. // 67 39 17 5 5 8 32 19 32 59 41 40 56 60 94 77 68 98 95 98
  150. // 5 5 8 17 19 32 32 39 40 41 56 59 60 67 68 77 94 95 98 98
  151. // 5 8 5 19 32 32 17 40 56 41 60 59 39 68 77 95 98 98 94 67