Browse Source

数据结构第五章作业

main
423A35C7 1 year ago
parent
commit
9933d31d1f
6 changed files with 388 additions and 0 deletions
  1. BIN
      作业/数据结构-金健/10213903403第五章作业.pdf
  2. +20
    -0
      作业/数据结构-金健/C++/第五章作业/CMakeLists.txt
  3. +177
    -0
      作业/数据结构-金健/C++/第五章作业/bitree.cpp
  4. +94
    -0
      作业/数据结构-金健/C++/第五章作业/main.cpp
  5. BIN
      作业/数据结构-金健/C++/第五章作业/release/chapter5.zip
  6. +97
    -0
      作业/数据结构-金健/C++/第五章作业/view.cpp

BIN
作业/数据结构-金健/10213903403第五章作业.pdf View File


+ 20
- 0
作业/数据结构-金健/C++/第五章作业/CMakeLists.txt View 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
- 0
作业/数据结构-金健/C++/第五章作业/bitree.cpp View 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
- 0
作业/数据结构-金健/C++/第五章作业/main.cpp View 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 View File


+ 97
- 0
作业/数据结构-金健/C++/第五章作业/view.cpp View 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…
Cancel
Save