SharedSchoolSpace/作业/数据结构-金健/C++/第七章作业/第七章作业2.cpp

168 lines
6.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by 423A35C7 on 2023-12-15.
//
// 09:19
// 20:06
#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <memory>
#include <vector>
template<typename T>
class BiSortNode {
public:
using NodePtr = std::unique_ptr<BiSortNode>;
// 好像这里没法使用initializer_listinitializer_list是对于多个相同值的初始化而不是一个东西的初始化参数列表
template<typename... Args>
explicit BiSortNode(Args... args, std::function<bool(T, T)> _compare) : data(args...) {
this->compare_function_(_compare);
}
template<typename... Args>
explicit BiSortNode(Args... args) : data(args...) {
this->compare_function_ = [](T&a, T&b) { return a < b; };
}
void update_depth_and_balance_factor() {
const int left_depth = this->left_child ? this->left_child->depth + 1 : 0;
const int right_depth = this->right_child ? this->right_child->depth + 1 : 0;
this->balance_factor = left_depth - right_depth;
this->depth = std::max(left_depth, right_depth);
}
// 这里的左旋指的是LL型需要进行的旋转名称不一定对
// 这部分用注释不好解释,建议最好搜一下网上的图解,理解了之后再看这部分代码
static void left_rotate(NodePtr&unbalanced) {
NodePtr pivot = std::move(unbalanced->left_child);
unbalanced->left_child = std::move(pivot->right_child);
pivot->right_child = std::move(unbalanced);
unbalanced = std::move(pivot);
unbalanced->update_depth_and_balance_factor();
unbalanced->right_child->update_depth_and_balance_factor();
}
// 这里的右旋指的是RR型需要进行的旋转名称不一定对
// 这部分用注释不好解释,建议最好搜一下网上的图解,理解了之后再看这部分代码
static void right_rotate(NodePtr&unbalanced) {
NodePtr pivot = std::move(unbalanced->right_child);
unbalanced->right_child = std::move(pivot->left_child);
pivot->left_child = std::move(unbalanced);
unbalanced = std::move(pivot);
unbalanced->update_depth_and_balance_factor();
unbalanced->left_child->update_depth_and_balance_factor();
}
static void insert(NodePtr&current_node, T new_data) {
// int balance_diff = 0;
if (new_data < current_node->data) {
// 如果新的节点比当前节点小就找它的左子树
if (current_node->left_child == nullptr) {
current_node->left_child = std::make_unique<BiSortNode>(new_data);
}
else {
current_node->insert(current_node->left_child, new_data);
}
}
else {
// 否则找右子树
if (current_node->right_child == nullptr) {
current_node->right_child = std::make_unique<BiSortNode>(new_data);
}
else {
current_node->insert(current_node->right_child, new_data);
}
}
current_node->update_depth_and_balance_factor();
if (current_node->balance_factor > 1) {
// 左子树比右子树高
assert(current_node->left_child->balance_factor != 0); // 此时左子树的平衡因子不应为0
if (current_node->left_child->balance_factor < 0) // 符合LR型
current_node->right_rotate(current_node->left_child); // 先进行右旋逆时针转化为LL
current_node->left_rotate(current_node); // 左旋(顺时针)
}
else if (current_node->balance_factor < -1) {
// 右子树比左子树高
assert(current_node->right_child->balance_factor != 0); // 此时右子树的平衡因子不应为0
if (current_node->right_child->balance_factor > 0) // 符合RL型
current_node->left_rotate(current_node->right_child); // 先进行左旋顺时针转化为RR型
current_node->right_rotate(current_node); // 右旋(逆时针)
}
// current_node->balance_factor += balance_diff;
current_node->update_depth_and_balance_factor();
// return balance_diff;
}
void inorder_traversal(std::vector<T>&output) {
if (this->left_child != nullptr) this->left_child->inorder_traversal(output);
output.push_back(this->data);
if (this->right_child != nullptr) this->right_child->inorder_traversal(output);
}
void preorder_traversal(std::vector<T>&output) {
output.push_back(this->data);
if (this->left_child != nullptr) this->left_child->preorder_traversal(output);
if (this->right_child != nullptr) this->right_child->preorder_traversal(output);
}
void postorder_traversal(std::vector<T>&output) {
if (this->left_child != nullptr) this->left_child->postorder_traversal(output);
if (this->right_child != nullptr) this->right_child->postorder_traversal(output);
output.push_back(this->data);
}
void traverse_and_output(std::ostream&out, std::function<void(std::vector<T>&)> traverse_function) {
std::vector<T> traverse_result;
traverse_function(traverse_result);
for (auto const&i: traverse_result)
std::cout << i << " ";
std::cout << std::endl;
}
private:
NodePtr left_child;
NodePtr right_child;
int balance_factor = 0; // 平衡因子
int depth = 0; // 树的深度(高度)
T data;
std::function<bool(T&, T&)> compare_function_;
};
int main() {
std::vector<int> origin_vector;
int temp;
while (std::cin >> temp) {
origin_vector.push_back(temp);
}
auto generator = origin_vector.cbegin();
BiSortNode<int>::NodePtr bi_sort_node{new BiSortNode<int>(*generator++)};
while (generator != origin_vector.cend()) {
bi_sort_node->insert(bi_sort_node, *generator++);
}
std::vector<int> traversal_result;
bi_sort_node->inorder_traversal(traversal_result);
std::cout << "为了便于验证,以下依次输出平衡二叉树的前序、中序、后序遍历结果:" << std::endl;
bi_sort_node->traverse_and_output(std::cout, [&bi_sort_node](std::vector<int>&output) {
bi_sort_node->preorder_traversal(output);
});
bi_sort_node->traverse_and_output(std::cout, [&bi_sort_node](std::vector<int>&output) {
bi_sort_node->inorder_traversal(output);
});
bi_sort_node->traverse_and_output(std::cout, [&bi_sort_node](std::vector<int>&output) {
bi_sort_node->postorder_traversal(output);
});
return 0;
}
// 输入:
// 98 77 94 67 59 60 56 68 95 98 32 39 32 17 5 5 8 19 40 41
// 输出:
// 为了便于验证,以下依次输出平衡二叉树的前序、中序、后序遍历结果:
// 67 39 17 5 5 8 32 19 32 59 41 40 56 60 94 77 68 98 95 98
// 5 5 8 17 19 32 32 39 40 41 56 59 60 67 68 77 94 95 98 98
// 5 8 5 19 32 32 17 40 56 41 60 59 39 68 77 95 98 98 94 67