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

//
// 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();
}
};