178 lines
5.3 KiB
C++
178 lines
5.3 KiB
C++
|
//
|
|||
|
// Created by 423A35C7 on 2023-11-12.
|
|||
|
//
|
|||
|
|
|||
|
// #include <functional>
|
|||
|
// #include <list>
|
|||
|
#include <cassert>
|
|||
|
#include <queue>
|
|||
|
#include <string>
|
|||
|
|
|||
|
struct Node {
|
|||
|
int num = 0;
|
|||
|
std::string text;
|
|||
|
// 线索化的标记
|
|||
|
bool if_left_chain = false;
|
|||
|
bool if_right_chain = false;
|
|||
|
// 左右子树或前驱后继
|
|||
|
Node* left = nullptr;
|
|||
|
Node* right = nullptr;
|
|||
|
|
|||
|
Node(int num, const std::string& text)
|
|||
|
: num(num),
|
|||
|
text(text) {
|
|||
|
}
|
|||
|
|
|||
|
~Node() {
|
|||
|
remove_left();
|
|||
|
remove_right();
|
|||
|
}
|
|||
|
|
|||
|
void remove_left() {
|
|||
|
if (left != nullptr && !if_left_chain) {
|
|||
|
// delete the node
|
|||
|
left->~Node();
|
|||
|
// delete the memory
|
|||
|
delete left;
|
|||
|
// set the pointer to nullptr
|
|||
|
left = nullptr;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void remove_right() {
|
|||
|
if (right != nullptr && !if_right_chain) {
|
|||
|
// delete the node
|
|||
|
right->~Node();
|
|||
|
// delete the memory
|
|||
|
delete right;
|
|||
|
// set the pointer to nullptr
|
|||
|
right = nullptr;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
class BiTree {
|
|||
|
Node *find(int num) {
|
|||
|
Node *temp;
|
|||
|
// 遍历查找num
|
|||
|
for (temp = head; temp && temp->num < num; temp = temp->right);
|
|||
|
return temp;
|
|||
|
}
|
|||
|
|
|||
|
void insert_left(Node *parent, const std::string& text) {
|
|||
|
// 断言parent不为空
|
|||
|
assert(parent != nullptr);
|
|||
|
// parent->remove_left();
|
|||
|
// 如果parent->left为空,则插入新节点
|
|||
|
if (parent->left == nullptr)
|
|||
|
parent->left = new Node {0, text};
|
|||
|
else
|
|||
|
insert_right(parent->left, text);
|
|||
|
}
|
|||
|
|
|||
|
void insert_right(Node *parent, const std::string& text) {
|
|||
|
// 断言parent不为空
|
|||
|
assert(parent != nullptr);
|
|||
|
// 记录tail
|
|||
|
Node *tail = parent;
|
|||
|
// 遍历查找tail->right
|
|||
|
for (; !tail->if_right_chain && tail->right; tail = tail->right);
|
|||
|
// 插入新节点
|
|||
|
tail->right = new Node {0, text};
|
|||
|
tail->if_right_chain = false;
|
|||
|
}
|
|||
|
public:
|
|||
|
Node *head;
|
|||
|
int length = 0;
|
|||
|
BiTree() {
|
|||
|
// 初始化头节点
|
|||
|
this->head = new Node(0, "");
|
|||
|
// 初始化节点数量
|
|||
|
this->length = 1;
|
|||
|
}
|
|||
|
~BiTree() {
|
|||
|
// 删除头节点的左右子节点
|
|||
|
this->head->remove_left();
|
|||
|
this->head->remove_right();
|
|||
|
// 删除头节点
|
|||
|
delete this->head;
|
|||
|
}
|
|||
|
|
|||
|
void update() {
|
|||
|
// 左节点入队,出队时扩展到所有的右节点
|
|||
|
std::queue<Node*> q;
|
|||
|
Node *current = head, *next = head->left;
|
|||
|
int current_num = 0;
|
|||
|
// while (!q.empty()) {
|
|||
|
// current->if_right_chain = true;
|
|||
|
// current->right = q.front();
|
|||
|
// current = q.front();
|
|||
|
// q.pop();
|
|||
|
// Node *next = current;
|
|||
|
// for (; next && !next->if_right_chain; current = next, next = next->right) {
|
|||
|
// next->num = current_num++;
|
|||
|
// if (next->left) {
|
|||
|
// q.push(next->left);
|
|||
|
// }
|
|||
|
// }
|
|||
|
// 当前节点为空,则跳出循环
|
|||
|
while (current) {
|
|||
|
// 当前节点的编号
|
|||
|
current->num = current_num++;
|
|||
|
// 如果当前节点有左子节点,则将左子节点放入队列
|
|||
|
if (current->left) {
|
|||
|
q.push(current->left);
|
|||
|
}
|
|||
|
|
|||
|
// 发生间断,从队列中重新取值
|
|||
|
if (!current->right || current->if_right_chain) {
|
|||
|
// 如果当前节点没有右子节点,或者当前节点已经处理完右子节点,则跳出循环
|
|||
|
if (q.empty()) break;
|
|||
|
// 从队列中取出下一个节点
|
|||
|
next = q.front();
|
|||
|
// 从队列中删除该节点
|
|||
|
q.pop();
|
|||
|
// 标记当前节点是线索化右子节点
|
|||
|
current->if_right_chain = true;
|
|||
|
} else {
|
|||
|
// 标记当前节点不是线索化右子节点
|
|||
|
current->if_right_chain = false;
|
|||
|
}
|
|||
|
// 将当前节点的右子节点设置为下一个节点
|
|||
|
current->right = next;
|
|||
|
// 将当前节点设置为下一个节点
|
|||
|
current = next;
|
|||
|
// 将下一个节点设置为下一个节点的右子节点
|
|||
|
next = next->right;
|
|||
|
}
|
|||
|
// 更新树的层数
|
|||
|
this->length = current_num;
|
|||
|
}
|
|||
|
|
|||
|
void insert(int num, std::queue<std::string> &children) {
|
|||
|
// 找到要插入的父节点
|
|||
|
Node *parent = this->find(num);
|
|||
|
// 断言父节点不为空
|
|||
|
assert(parent != nullptr);
|
|||
|
// 如果子节点为空,则直接返回
|
|||
|
if (children.empty()) return;
|
|||
|
// 插入左子节点
|
|||
|
this->insert_left(parent, children.front());
|
|||
|
// 从队列中弹出第一个子节点
|
|||
|
children.pop();
|
|||
|
// 将父节点指向左子节点
|
|||
|
parent = parent->left;
|
|||
|
// 如果队列不为空,则插入右子节点
|
|||
|
while (!children.empty()) {
|
|||
|
this->insert_right(parent, children.front());
|
|||
|
// 从队列中弹出第一个子节点
|
|||
|
children.pop();
|
|||
|
// 将父节点指向右子节点
|
|||
|
parent = parent->right;
|
|||
|
}
|
|||
|
// 更新树的序号
|
|||
|
this->update();
|
|||
|
}
|
|||
|
};
|
|||
|
|