SharedSchoolSpace/作业/数据结构-金健/C++/第六章作业/graph.hpp

236 lines
6.3 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-02.
//
#ifndef GRAPH_H
#define GRAPH_H
#include <algorithm>
#include <iostream>
#include <memory>
#include <random>
#include <cstring>
#include <list>
#include <map>
std::default_random_engine engine(time(nullptr));
class MergeFindSet {
using int_ptr = std::unique_ptr<int>;
public:
const int length;
explicit MergeFindSet(const int n)
: length(n), elements(new int[n]) {
memset(this->elements.get(), -1, n * sizeof(int));
}
int find(const int index) {
return elements.get()[index] == -1
? index
: elements.get()[index] = find(elements.get()[index]);
}
void merge(const int a, const int b) {
elements.get()[find(b)] = find(a);
}
friend std::ostream& operator<<(std::ostream&out, const MergeFindSet&merge_find_set);
private:
int_ptr elements;
};
std::ostream& operator<<(std::ostream&out, const MergeFindSet&merge_find_set) {
for (int i = 0; i < merge_find_set.length; ++i) {
out << merge_find_set.elements.get()[i] << "\t";
}
return out;
}
/**
* \brief 打印高维类型
* \tparam T 最内层的类型
* \param high_dimension 高维指针,应为 int**, bool*** 等类似的类型
* \param length 长度(每一维的长度都应一样)
* \param dimensino_num 维度
*/
template<typename T>
void print(void* high_dimension, const int length, const int dimensino_num = 1) {
void** temp = static_cast<void **>(high_dimension);
if (dimensino_num <= 1) {
for (int i = 0; i < length; ++i) {
std::cout << static_cast<T *>(high_dimension)[i] << "\t";
}
std::cout << std::endl;
return;
}
for (int i = 0; i < length; ++i) {
print<T>(temp[i], length, dimensino_num - 1);
}
std::cout << std::endl;
}
class Graph {
public:
~Graph() {
for (int i = 0; i < this->node_num; ++i) {
delete this->adjacency[i];
}
delete this->adjacency;
for (int i = 0; i < this->node_num; ++i) {
delete this->incidence[i];
}
delete this->incidence;
}
explicit Graph(const int n)
: merge_find_set_(n) {
this->node_num = n;
std::uniform_int_distribution<int> get_random(1, 100);
this->adjacency = new int *[n];
this->incidence = new bool *[n];
for (int i = 0; i < n; ++i) {
this->adjacency[i] = new int[n];
this->incidence[i] = new bool[n];
memset(this->incidence[i], 0, n * sizeof(bool));
this->adjacency[i][i] = INT_MAX;
for (int j = 0; j < i; ++j) {
this->adjacency[i][j] = this->adjacency[j][i] = get_random(engine);
}
}
}
void print_adjacency() const {
print<int>(this->adjacency, this->node_num, 2);
}
void print_incidence() const {
print<bool>(this->incidence, this->node_num, 2);
}
void print_merge_find_set() {
std::cout << this->merge_find_set_ << std::endl;
}
bool same_league(const int start, const int target) {
return this->merge_find_set_.find(start) == this->merge_find_set_.find(target);
}
/**
* \brief 把目标城市所在联盟合并到起始城市所在联盟中
* \param start 起始城市
* \param target 目标城市
*/
void merge(const int start, const int target) {
this->merge_find_set_.merge(start, target);
}
/**
* \brief 开始记录关系矩阵是否被改变
*/
void start_record_incidence() {
this->incidence_had_changed = false;
}
/**
* \brief 停止记录并返回关系矩阵是否被改变
* \return 关系矩阵是否被改变
*/
bool stop_record_incidence() {
const bool temp = this->incidence_had_changed;
this->incidence_had_changed = false;
return temp;
}
friend void one_turn(Graph*);
protected:
/**
* \brief 邻接矩阵,表示任意两个城市之间的距离
*/
int** adjacency; // 邻接矩阵
/**
* \brief 城市数量
*/
int node_num;
/**
* \brief 关系矩阵任意两个城市之间如果有直接的公路则为true是对称的反自反的关系不一定满足传递性
*/
bool** incidence; // 关系矩阵
bool incidence_had_changed;
MergeFindSet merge_find_set_;
};
class ComplexGraph : public Graph {
public:
~ComplexGraph() {
// this->~Graph(); // 好像析构函数会自动调用,不需要手动调用
delete this->alpha;
}
explicit ComplexGraph(const int n)
: Graph(n) {
this->alpha = new int[n];
std::uniform_int_distribution<int> get_random(1, n / 2);
for (int i = 0; i < n; ++i) {
this->alpha[i] = get_random(engine);
}
}
void print_alpha() {
// print<int>(this->alpha, this->node_num, 1);
std::map<int, std::list<int>> index_to_league;
for (int i = 0; i < this->node_num; ++i) {
int ancestor = this->merge_find_set_.find(i);
if (!index_to_league.contains(ancestor)) {
index_to_league.insert({ancestor, {}});
}
index_to_league[ancestor].push_back(i);
}
for (const auto&[ancestor, child]: index_to_league) {
std::cout << "城市联盟 { ";
for (auto value: child) {
std::cout << value << " ";
}
std::cout << " } 的规模系数为 ";
std::cout << this->get_alpha(ancestor) << std::endl;
}
}
void set_beta(const int beta) {
this->beta = beta;
}
/**
* \brief 获取城市所在联盟的规模系数
* \param index 城市序号
* \return 城市所在联盟的规模系数
*/
[[nodiscard]] int get_alpha(const int index) {
return this->alpha[this->merge_find_set_.find(index)];
}
/**
* \brief 城市所在联盟的规模系数增加1
* \param index 城市序号
*/
void increase_alpha(const int index) {
this->alpha[this->merge_find_set_.find(index)]++;
}
friend void one_turn(ComplexGraph*);
private:
/**
* \brief 每个城市的规模系数
*/
int* alpha;
int beta = 0; // 限定系数
};
#endif //GRAPH_H