Przeglądaj źródła

数据结构——第六章作业

main
423A35C7 11 miesięcy temu
rodzic
commit
d1e111b62d
6 zmienionych plików z 498 dodań i 0 usunięć
  1. BIN
      作业/数据结构-金健/10213903403第六章作业.pdf
  2. +10
    -0
      作业/数据结构-金健/C++/第六章作业/CMakeLists.txt
  3. +235
    -0
      作业/数据结构-金健/C++/第六章作业/graph.hpp
  4. BIN
      作业/数据结构-金健/C++/第六章作业/release/chapter6.zip
  5. +93
    -0
      作业/数据结构-金健/C++/第六章作业/第六章作业1.cpp
  6. +160
    -0
      作业/数据结构-金健/C++/第六章作业/第六章作业2.cpp

BIN
作业/数据结构-金健/10213903403第六章作业.pdf Wyświetl plik


+ 10
- 0
作业/数据结构-金健/C++/第六章作业/CMakeLists.txt Wyświetl plik

@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.26)
project(chapter6)
set(CMAKE_CXX_STANDARD 23)
add_executable(graph1 第六章作业1.cpp)
add_executable(graph2 第六章作业2.cpp)
SET(EXECUTABLE_OUTPUT_PATH R:/)
set(CMAKE_CXX_FLAGS_RELEASE -fexec-charset=GBK)

+ 235
- 0
作业/数据结构-金健/C++/第六章作业/graph.hpp Wyświetl plik

@ -0,0 +1,235 @@
//
// 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

BIN
作业/数据结构-金健/C++/第六章作业/release/chapter6.zip Wyświetl plik


+ 93
- 0
作业/数据结构-金健/C++/第六章作业/第六章作业1.cpp Wyświetl plik

@ -0,0 +1,93 @@
/*
*
* 1. 使merge或者inplace_merge
* 2. 使priority_queue
* 3. 使multiset
*
* $n$$n^2$
* n-1
* merge吧
*/
/*
*
* ABC三个城市存在环A申请修建ABB申请修建BCC申请修建CA
* AB < AC, BC < BA, CA < CB
* AB < AC < BC < ABAB < AB是不可能的
* n个城市n > 2
*/
/*
* n个城市一轮后就会修建了
* n条公路n-1使
*/
#include <iostream>
#include "graph.hpp"
// 一轮
void one_turn(Graph* graph) {
for (int start = 0; start < graph->node_num; ++start) {
int target;
while (true) {
int* target_ptr = std::min_element(graph->adjacency[start],
graph->adjacency[start] + graph->node_num);
// 如果最小的目标城市距离都是INT_MAX,则说明start与所有城市都已连通,则不再修建
if (*target_ptr == INT_MAX) {
return;
}
target = target_ptr - graph->adjacency[start];
// 如果在同一个城市联盟内,那么把这个目标城市排除,在剩下的目标城市中继续
if (graph->same_league(start, target)) {
graph->adjacency[start][target] = INT_MAX;
continue;
}
// 如果已经修建过了,则换个目标城市
if (graph->incidence[start][target]) {
continue;
}
// 不需要考虑三个或以上成环的情况
break;
}
// 修建公路,即在关系矩阵上将相应的行列置为true
graph->incidence[start][target] = graph->incidence[target][start] = true;
// 把目标城市所在联盟合并到起始城市所在联盟中
graph->merge(start, target);
}
}
int main() {
int n;
std::cout << "输入城市的个数:";
std::cin >> n;
auto graph = Graph(n);
std::cout << "初始的距离的邻接矩阵为:" << std::endl;
graph.print_adjacency();
one_turn(&graph);
std::cout << "第一轮后的关系矩阵如下:" << std::endl;
graph.print_incidence();
std::cout << "并查集如下:" << std::endl;
graph.print_merge_find_set();
std::cout << "可以看到,一轮后就已经全部连通。" << std::endl;
return 0;
}
// 输入城市的个数:5
// 初始的距离的邻接矩阵为:
// 2147483647 69 19 14 90
// 69 2147483647 66 82 66
// 19 66 2147483647 48 8
// 14 82 48 2147483647 22
// 90 66 8 22 2147483647
//
// 第一轮后的关系矩阵如下:
// 0 0 0 1 0
// 0 0 1 0 0
// 0 1 0 0 1
// 1 0 0 0 1
// 0 0 1 1 0
//
// 并查集如下:
// -1 0 0 0 0
// 可以看到,一轮后就已经全部连通。

+ 160
- 0
作业/数据结构-金健/C++/第六章作业/第六章作业2.cpp Wyświetl plik

@ -0,0 +1,160 @@
//
// Created by 423A35C7 on 2023-12-02.
//
#include <iostream>
#include "graph.hpp"
// 这次执行一轮后不一定结束了,
void one_turn(ComplexGraph* graph) {
for (int start = 0; start < graph->node_num; ++start) {
int target;
while (true) {
int* target_ptr = std::min_element(graph->adjacency[start],
graph->adjacency[start] + graph->node_num);
// 如果最小的目标城市距离都是INT_MAX,则说明start与所有城市都已连通,则不再修建
if (*target_ptr == INT_MAX) {
return;
}
target = target_ptr - graph->adjacency[start];
// 如果在同一个城市联盟内,那么把这个目标城市排除,在剩下的目标城市中继续
if (graph->same_league(start, target)) {
graph->adjacency[start][target] = INT_MAX;
continue;
}
// 如果已经修建过了,则换个目标城市
if (graph->incidence[start][target]) {
continue;
}
// 不需要考虑三个或以上成环的情况
break;
}
const int start_alpha = graph->get_alpha(start);
const int target_alpha = graph->get_alpha(target);
// 当城市规模系数α到达限定系数β后,我们认为该 league
// 已经到达“稳定”,不再与任何其他城市修建公路。
if (start_alpha >= graph->beta || target_alpha >= graph->beta) {
continue;
}
if (start_alpha < target_alpha) {
// 规模小于目标城市,则政府拒绝修建
continue;
}
else if (start_alpha == target_alpha) {
// 若两个城市规模相等,则修建过后两座城市形成的 league 城市规模系数α增一
graph->increase_alpha(start);
}
else if (start_alpha > target_alpha) {
// 若大于目标城市,则同意修建,规模系数不变
;
}
// 修建公路,即在关系矩阵上将相应的行列置为true
graph->incidence[start][target] = graph->incidence[target][start] = true;
graph->incidence_had_changed = true; // 保护字段为什么能直接访问?
// 把目标城市所在联盟合并到起始城市所在联盟中
graph->merge(start, target);
}
}
int main() {
int n, beta;
std::cout << "输入城市的个数:";
std::cin >> n;
auto graph = ComplexGraph(n);
std::cout << "初始的城市规模为:" << std::endl;
graph.print_alpha();
std::cout << "请输入限定系数beta:";
std::cin >> beta;
graph.set_beta(beta);
std::cout << "初始的距离的邻接矩阵为:" << std::endl;
graph.print_adjacency();
for (int turn_num = 1; ; turn_num++) {
graph.start_record_incidence();
one_turn(&graph);
// 当关系矩阵不再被改变,也就是说明不再修桥了,则说明达到稳定
if (!graph.stop_record_incidence()) {
break;
}
std::cout << "" << turn_num << "轮后的关系矩阵如下:" << std::endl;
graph.print_incidence();
std::cout << "规模系数如下:" << std::endl;
graph.print_alpha();
std::cout << "并查集如下:" << std::endl;
graph.print_merge_find_set();
std::cout << std::endl;
}
std::cout << "已经达到稳定" << std::endl;
return 0;
}
// 输入城市的个数:10
// 初始的城市规模为:
// 城市联盟 { 0 } 的规模系数为 2
// 城市联盟 { 1 } 的规模系数为 5
// 城市联盟 { 2 } 的规模系数为 2
// 城市联盟 { 3 } 的规模系数为 1
// 城市联盟 { 4 } 的规模系数为 3
// 城市联盟 { 5 } 的规模系数为 4
// 城市联盟 { 6 } 的规模系数为 2
// 城市联盟 { 7 } 的规模系数为 2
// 城市联盟 { 8 } 的规模系数为 4
// 城市联盟 { 9 } 的规模系数为 3
// 请输入限定系数beta:5
// 初始的距离的邻接矩阵为:
// 2147483647 63 39 34 97 93 35 42 68 29
// 63 2147483647 11 100 82 48 31 2 33 58
// 39 11 2147483647 85 100 27 47 97 86 91
// 34 100 85 2147483647 15 32 16 77 84 29
// 97 82 100 15 2147483647 4 53 63 54 29
// 93 48 27 32 4 2147483647 25 85 86 58
// 35 31 47 16 53 25 2147483647 97 27 88
// 42 2 97 77 63 85 97 2147483647 61 91
// 68 33 86 84 54 86 27 61 2147483647 66
// 29 58 91 29 29 58 88 91 66 2147483647
//
// 第1轮后的关系矩阵如下:
// 0 0 0 0 0 0 0 0 0 1
// 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 1 0 0 0
// 0 0 0 0 0 1 0 0 0 0
// 0 0 0 0 1 0 0 0 0 0
// 0 0 0 1 0 0 0 0 1 0
// 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 1 0 0 0
// 1 0 0 0 0 0 0 0 0 0
//
// 规模系数如下:
// 城市联盟 { 1 } 的规模系数为 5
// 城市联盟 { 2 } 的规模系数为 2
// 城市联盟 { 4 5 } 的规模系数为 4
// 城市联盟 { 7 } 的规模系数为 2
// 城市联盟 { 3 6 8 } 的规模系数为 4
// 城市联盟 { 0 9 } 的规模系数为 3
// 并查集如下:
// 9 -1 -1 8 5 -1 8 -1 -1 -1
//
// 第2轮后的关系矩阵如下:
// 0 0 0 0 0 0 0 0 0 1
// 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 1 0 1 0 0 0
// 0 0 0 1 0 1 0 0 0 0
// 0 0 0 0 1 0 0 0 0 0
// 0 0 0 1 0 0 0 0 1 0
// 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 1 0 0 0
// 1 0 0 0 0 0 0 0 0 0
//
// 规模系数如下:
// 城市联盟 { 1 } 的规模系数为 5
// 城市联盟 { 2 } 的规模系数为 2
// 城市联盟 { 7 } 的规模系数为 2
// 城市联盟 { 3 4 5 6 8 } 的规模系数为 5
// 城市联盟 { 0 9 } 的规模系数为 3
// 并查集如下:
// 9 -1 -1 8 8 8 8 -1 -1 -1
//
// 已经达到稳定

Ładowanie…
Anuluj
Zapisz