用于存放学校的作业便于复习。
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.

177 lines
5.3 KiB

  1. //
  2. // Created by 423A35C7 on 2023-11-12.
  3. //
  4. // #include <functional>
  5. // #include <list>
  6. #include <cassert>
  7. #include <queue>
  8. #include <string>
  9. struct Node {
  10. int num = 0;
  11. std::string text;
  12. // 线索化的标记
  13. bool if_left_chain = false;
  14. bool if_right_chain = false;
  15. // 左右子树或前驱后继
  16. Node* left = nullptr;
  17. Node* right = nullptr;
  18. Node(int num, const std::string& text)
  19. : num(num),
  20. text(text) {
  21. }
  22. ~Node() {
  23. remove_left();
  24. remove_right();
  25. }
  26. void remove_left() {
  27. if (left != nullptr && !if_left_chain) {
  28. // delete the node
  29. left->~Node();
  30. // delete the memory
  31. delete left;
  32. // set the pointer to nullptr
  33. left = nullptr;
  34. }
  35. }
  36. void remove_right() {
  37. if (right != nullptr && !if_right_chain) {
  38. // delete the node
  39. right->~Node();
  40. // delete the memory
  41. delete right;
  42. // set the pointer to nullptr
  43. right = nullptr;
  44. }
  45. }
  46. };
  47. class BiTree {
  48. Node *find(int num) {
  49. Node *temp;
  50. // 遍历查找num
  51. for (temp = head; temp && temp->num < num; temp = temp->right);
  52. return temp;
  53. }
  54. void insert_left(Node *parent, const std::string& text) {
  55. // 断言parent不为空
  56. assert(parent != nullptr);
  57. // parent->remove_left();
  58. // 如果parent->left为空,则插入新节点
  59. if (parent->left == nullptr)
  60. parent->left = new Node {0, text};
  61. else
  62. insert_right(parent->left, text);
  63. }
  64. void insert_right(Node *parent, const std::string& text) {
  65. // 断言parent不为空
  66. assert(parent != nullptr);
  67. // 记录tail
  68. Node *tail = parent;
  69. // 遍历查找tail->right
  70. for (; !tail->if_right_chain && tail->right; tail = tail->right);
  71. // 插入新节点
  72. tail->right = new Node {0, text};
  73. tail->if_right_chain = false;
  74. }
  75. public:
  76. Node *head;
  77. int length = 0;
  78. BiTree() {
  79. // 初始化头节点
  80. this->head = new Node(0, "");
  81. // 初始化节点数量
  82. this->length = 1;
  83. }
  84. ~BiTree() {
  85. // 删除头节点的左右子节点
  86. this->head->remove_left();
  87. this->head->remove_right();
  88. // 删除头节点
  89. delete this->head;
  90. }
  91. void update() {
  92. // 左节点入队,出队时扩展到所有的右节点
  93. std::queue<Node*> q;
  94. Node *current = head, *next = head->left;
  95. int current_num = 0;
  96. // while (!q.empty()) {
  97. // current->if_right_chain = true;
  98. // current->right = q.front();
  99. // current = q.front();
  100. // q.pop();
  101. // Node *next = current;
  102. // for (; next && !next->if_right_chain; current = next, next = next->right) {
  103. // next->num = current_num++;
  104. // if (next->left) {
  105. // q.push(next->left);
  106. // }
  107. // }
  108. // 当前节点为空,则跳出循环
  109. while (current) {
  110. // 当前节点的编号
  111. current->num = current_num++;
  112. // 如果当前节点有左子节点,则将左子节点放入队列
  113. if (current->left) {
  114. q.push(current->left);
  115. }
  116. // 发生间断,从队列中重新取值
  117. if (!current->right || current->if_right_chain) {
  118. // 如果当前节点没有右子节点,或者当前节点已经处理完右子节点,则跳出循环
  119. if (q.empty()) break;
  120. // 从队列中取出下一个节点
  121. next = q.front();
  122. // 从队列中删除该节点
  123. q.pop();
  124. // 标记当前节点是线索化右子节点
  125. current->if_right_chain = true;
  126. } else {
  127. // 标记当前节点不是线索化右子节点
  128. current->if_right_chain = false;
  129. }
  130. // 将当前节点的右子节点设置为下一个节点
  131. current->right = next;
  132. // 将当前节点设置为下一个节点
  133. current = next;
  134. // 将下一个节点设置为下一个节点的右子节点
  135. next = next->right;
  136. }
  137. // 更新树的层数
  138. this->length = current_num;
  139. }
  140. void insert(int num, std::queue<std::string> &children) {
  141. // 找到要插入的父节点
  142. Node *parent = this->find(num);
  143. // 断言父节点不为空
  144. assert(parent != nullptr);
  145. // 如果子节点为空,则直接返回
  146. if (children.empty()) return;
  147. // 插入左子节点
  148. this->insert_left(parent, children.front());
  149. // 从队列中弹出第一个子节点
  150. children.pop();
  151. // 将父节点指向左子节点
  152. parent = parent->left;
  153. // 如果队列不为空,则插入右子节点
  154. while (!children.empty()) {
  155. this->insert_right(parent, children.front());
  156. // 从队列中弹出第一个子节点
  157. children.pop();
  158. // 将父节点指向右子节点
  159. parent = parent->right;
  160. }
  161. // 更新树的序号
  162. this->update();
  163. }
  164. };