diff --git a/作业/数据结构-金健/10213903403第五章作业.pdf b/作业/数据结构-金健/10213903403第五章作业.pdf new file mode 100644 index 0000000..d76b2ec Binary files /dev/null and b/作业/数据结构-金健/10213903403第五章作业.pdf differ diff --git a/作业/数据结构-金健/C++/第五章作业/CMakeLists.txt b/作业/数据结构-金健/C++/第五章作业/CMakeLists.txt new file mode 100644 index 0000000..a23ae15 --- /dev/null +++ b/作业/数据结构-金健/C++/第五章作业/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.9) +project(chapter5) + +# set(CMAKE_CXX_STANDARD 11) + +# include_directories( +# include +# ) + +add_executable(bitree + main.cpp) + +SET(EXECUTABLE_OUTPUT_PATH R:/) + +if (CMAKE_BUILD_TYPE STREQUAL Release) +# # 也可以set(CMAKE_CXX_FLAGS_RELEASE ...) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fexec-charset=GBK") +endif() + +target_link_libraries(bitree) \ No newline at end of file diff --git a/作业/数据结构-金健/C++/第五章作业/bitree.cpp b/作业/数据结构-金健/C++/第五章作业/bitree.cpp new file mode 100644 index 0000000..4f890aa --- /dev/null +++ b/作业/数据结构-金健/C++/第五章作业/bitree.cpp @@ -0,0 +1,177 @@ +// +// Created by 423A35C7 on 2023-11-12. +// + +// #include +// #include +#include +#include +#include + +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 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 &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(); + } +}; + diff --git a/作业/数据结构-金健/C++/第五章作业/main.cpp b/作业/数据结构-金健/C++/第五章作业/main.cpp new file mode 100644 index 0000000..679f2b8 --- /dev/null +++ b/作业/数据结构-金健/C++/第五章作业/main.cpp @@ -0,0 +1,94 @@ +// +// Created by 423A35C7 on 2023-11-12. +// +// 14:55 +// 16:57 + +#include "view.cpp" + +int main() { + // 创建二叉树 + BiTree bi_tree; + // 父节点编号 + int parent = 0; + // 子节点队列 + std::queue children; + // 文本 + std::string text; + // 文本长度 + text.reserve(100); + // 临时变量 + int temp; + // 错误信息 + std::string error_message; + // 重新输入 + next_input: + // 清屏 + clear_screen(); + // 输出二叉树 + output(bi_tree.head, 1, 1); + // 移动光标到指定位置 + moveto(100, 1); + // 输出提示信息 + std::cout << error_message << std::endl << "输入整数编号和字符串文本,空格分隔,输入单个非数字字符表示结束:" << std::endl;; + // 循环输入 + while (std::cin >> parent) { + // 如果编号不存在 + if (parent >= bi_tree.length) { + // 设置错误信息 + error_message = "输入的编号不存在,请重新输入:"; + // 忽略输入 + std::cin.ignore(1024, '\n'); + // 重新输入 + goto next_input; + } + // 循环输入 + while ((temp = std::cin.get()) > 0) { + // 根据输入的值进行判断 + switch (temp) { + // 换行符 + case '\n': + // 如果文本不为空 + if (!text.empty()) { + // 将文本添加到子节点队列中 + children.push(text); + // 清空文本 + text.clear(); + } + // 将父节点编号和子节点队列插入二叉树 + bi_tree.insert(parent, children); + // 重新输入 + goto next_input; + // 空格 + case ' ': + // 如果文本不为空 + if (!text.empty()) { + // 将文本添加到子节点队列中 + children.push(text); + // 清空文本 + text.clear(); + } + break; + // 其他字符 + default: + // 将字符添加到文本中 + text.push_back(temp); + break; + } + } + } + // 添加节点 + // children.emplace("张三"); + // children.emplace("李四"); + // children.emplace("王五"); + // bi_tree.insert(parent, children); + // parent = 2; + // children.emplace("师大"); + // children.emplace("统计"); + // children.emplace("计算机"); + // bi_tree.insert(parent, children); + // parent = 0; + // children.emplace("赵六"); + // bi_tree.insert(parent, children); + return 0; +} \ No newline at end of file diff --git a/作业/数据结构-金健/C++/第五章作业/release/chapter5.zip b/作业/数据结构-金健/C++/第五章作业/release/chapter5.zip new file mode 100644 index 0000000..aac4575 Binary files /dev/null and b/作业/数据结构-金健/C++/第五章作业/release/chapter5.zip differ diff --git a/作业/数据结构-金健/C++/第五章作业/view.cpp b/作业/数据结构-金健/C++/第五章作业/view.cpp new file mode 100644 index 0000000..c52b028 --- /dev/null +++ b/作业/数据结构-金健/C++/第五章作业/view.cpp @@ -0,0 +1,97 @@ +// +// Created by 423A35C7 on 2023-11-12. +// +// 11:47 +// 14:55 + +#include +#include +#include +#include "bitree.cpp" + +#define move_and_output(x, y, str) printf("\033[s\033[%d;%dH%s\033u", x, y, str) +// 移动并输出到指定位置 +#define moveto(x, y) printf("\033[s\033[%d;%dH", x, y) +// 移动到指定位置 +#define movedown(x) printf("\033[%dB", (x)) +// 向下移动指定行 +#define save_cursor() printf("\033[s") +// 保存光标位置 +#define restore_cursor() printf("\033[u") +// 恢复光标位置 +#define clear_char(num) \ +for (int i = 0; i < num; i++) \ +printf(" ") +// 清空指定位置的字符 +#define clear_screen() printf("\033[2J") + +// class ViewBox { +// Node *left_node; +// int x, y; +// int width; +// int height; +// struct Size { +// int width; +// int height; +// }; +// Size calculate_size(Node *left_node) { +// Size size {left_node->text.length(), 1}; +// if (left_node->left) { +// Size increment; +// increment = calculate_size(left_node->left); +// +// } +// } +// }; + +enum LINE {NONE, HORIZONTAL, VERTICAL}; + +int get_length(Node *node) { + // 2是_和空格的长度 + return std::to_string(node->num).length() + 2 + node->text.length(); +} + +void print(Node *node, int x, int y, LINE line_type) { + // 移动到指定位置 + moveto(2 * x, y); + // 保存当前光标位置 + save_cursor(); + // 如果line_type为VERTICAL,则输出“|” + if (line_type == VERTICAL) { + std::cout << "|"; + } + // 恢复光标位置 + restore_cursor(); + // 向下移动1个单位 + movedown(1); + // 如果line_type为HORIZONTAL,则输出“——” + if (line_type == HORIZONTAL) { + std::cout << "——"; + } + // 输出node的num和text + std::cout << node->num << "_" << node->text << " "; +} + +int output(Node *left_node, int x, int y) { + int width = 0; + if (left_node == nullptr) return width; + // 打印左节点 + print(left_node, x, y, VERTICAL); + // 计算宽度 + width += std::max(get_length(left_node), output(left_node->left, x + 1, y + width)); + // 遍历右节点 + for (Node *temp = left_node; temp->right && !temp->if_right_chain; temp = temp->right) { + // 打印右节点 + print(temp->right, x, y + width, HORIZONTAL); + // 计算宽度 + // 2是——的长度 + width += std::max(2 + get_length(temp->right), output(temp->right->left, x + 1, y + width)); + // width += temp->right->text.length(); + } + return width; + // if (left_node->left == nullptr) { + // return width; + // } + // depth += 1; + // return std::max(width, output(left_node->left, depth)); +} \ No newline at end of file