数据结构第五章作业
This commit is contained in:
parent
0509105b35
commit
9933d31d1f
BIN
作业/数据结构-金健/10213903403第五章作业.pdf
Normal file
BIN
作业/数据结构-金健/10213903403第五章作业.pdf
Normal file
Binary file not shown.
20
作业/数据结构-金健/C++/第五章作业/CMakeLists.txt
Normal file
20
作业/数据结构-金健/C++/第五章作业/CMakeLists.txt
Normal file
@ -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)
|
177
作业/数据结构-金健/C++/第五章作业/bitree.cpp
Normal file
177
作业/数据结构-金健/C++/第五章作业/bitree.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
//
|
||||
// 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();
|
||||
}
|
||||
};
|
||||
|
94
作业/数据结构-金健/C++/第五章作业/main.cpp
Normal file
94
作业/数据结构-金健/C++/第五章作业/main.cpp
Normal file
@ -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<std::string> 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;
|
||||
}
|
BIN
作业/数据结构-金健/C++/第五章作业/release/chapter5.zip
Normal file
BIN
作业/数据结构-金健/C++/第五章作业/release/chapter5.zip
Normal file
Binary file not shown.
97
作业/数据结构-金健/C++/第五章作业/view.cpp
Normal file
97
作业/数据结构-金健/C++/第五章作业/view.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
//
|
||||
// Created by 423A35C7 on 2023-11-12.
|
||||
//
|
||||
// 11:47
|
||||
// 14:55
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#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));
|
||||
}
|
Loading…
Reference in New Issue
Block a user