Commit 22a66b31 authored by CDK6182CHR's avatar CDK6182CHR
Browse files

2021.5.20 Graph, UFSet

parent cbea400b
#include <iostream>
#include <utility>
/// <summary>
/// 教材 p.362
/// 具有固定结点数的有向图的邻接多重表实现 或十字链表
/// 仍然采用int在内部表示结点
/// </summary>
/// <typeparam name="V"></typeparam>
/// <typeparam name="E"></typeparam>
template <typename V,typename E>
class CrossGraph {
public:
//表示从v1到v2的有向边
struct Edge {
E edata;
int v1, v2;
Edge* path1; //出边表
Edge* path2; //入边表
Edge():edata(),v1(),v2(),path1(nullptr),path2(nullptr){}
Edge(int v1_,int v2_,const E& data):edata(data),v1(v1_),v2(v2_),
path1(nullptr),path2(nullptr){}
};
struct Vertex {
V vdata;
Edge* ined; //入边表
Edge* outed; //出边表
Vertex():vdata(),ined(nullptr),outed(nullptr){}
};
CrossGraph(int size_);
~CrossGraph()noexcept;
Edge* add_edge(int from, int to, const E& data);
void add_biedge(int x, int y, const E& data);
void remove_edge(int from, int to); //需要时实现
inline Edge* first_out_edge(int v) {
return vertices[v].outed;
}
inline Edge* next_out_edge(Edge* e) {
return e->path1;
}
Edge* first_in_edge(int v) {
return vertices[v].ined;
}
Edge* next_in_edge(Edge* e) {
return e->path2;
}
inline int get_size()const {
return size;
}
CrossGraph(const CrossGraph&) = delete;
CrossGraph(CrossGraph&&) = delete;
CrossGraph& operator=(const CrossGraph&) = delete;
CrossGraph& operator=(CrossGraph&&) = delete;
protected:
int size; //顶点数
Vertex* vertices;
};
template<typename V, typename E>
CrossGraph<V, E>::CrossGraph(int size_):size(size_)
{
vertices = new Vertex[size];
}
template<typename V, typename E>
CrossGraph<V, E>::~CrossGraph() noexcept
{
//先按照出边顺序清除表
for (int i = 0; i < size; i++) {
auto e = vertices[i].outed;
if (e) {
auto e1 = e->path1;
while (e1) {
delete e;
e = e1;
e1 = e1->path1;
}
}
}
delete[] vertices;
vertices = nullptr;
}
//注意 插入到各个边的链表的第一位
template<typename V, typename E>
typename CrossGraph<V,E>::Edge*
CrossGraph<V, E>::add_edge(int from, int to, const E& data)
{
auto e = new Edge(from, to, data);
e->path1 = vertices[from].outed;
vertices[from].outed = e;
e->path2 = vertices[to].ined;
vertices[to].ined = e;
return e;
}
template<typename V, typename E>
void CrossGraph<V, E>::add_biedge(int x, int y, const E& data)
{
add_edge(x, y, data);
add_edge(y, x, data);
}
#include <iostream>
#include <cstdio>
#include <utility>
/// <summary>
/// 有向图的邻接表表示。暂时只考虑插入的情况。
/// 只维护出边而不维护入边。
/// </summary>
/// <typeparam name="V"></typeparam>
/// <typeparam name="E"></typeparam>
template <typename V,typename E>
class Graph {
public:
struct Edge;
struct Vertex {
V vdata;
Edge* adj;
Vertex():vdata(),adj(nullptr){}
};
struct Edge {
E edata;
int to;
Edge* link;
Edge(int to_) :edata(), to(to_), link(nullptr){}
Edge(int to_,const E& data):edata(data),to(to_),link(nullptr){}
};
Graph(int size_);
~Graph();
Edge* add_edge(int from, int to, const E& data);
//添加双向边
void add_biedge(int a, int b, const E& data);
Edge* first_edge(int v);
inline int get_size()const {
return size;
}
Graph(const Graph&) = delete;
Graph(Graph&&) = delete;
Graph& operator=(const Graph&) = delete;
Graph& operator=(Graph&&) = delete;
protected:
int size;
Vertex* vertices;
};
template<typename V, typename E>
Graph<V, E>::Graph(int size_):size(size_)
{
vertices = new Vertex[size];
}
template<typename V, typename E>
Graph<V, E>::~Graph()
{
for (int i = 0; i < size; i++) {
Edge* t = vertices[i].adj;
if (t) {
Edge* t1 = t->link;
while (t1) {
delete t;
t = t1;
t1 = t1->link;
}
}
vertices[i].adj = nullptr;
}
delete[] vertices;
vertices = nullptr;
}
// 注意 这是插入到第一个
template<typename V, typename E>
typename Graph<V,E>::Edge* Graph<V, E>::add_edge(int from, int to, const E& data)
{
Edge* e = new Edge(to, data);
e->link = vertices[from].adj;
vertices[from].adj = e;
return e;
}
template<typename V, typename E>
void Graph<V, E>::add_biedge(int a, int b, const E& data)
{
add_edge(a, b, data);
add_edge(b, a, data);
}
template<typename V, typename E>
typename Graph<V,E>::Edge* Graph<V, E>::first_edge(int v)
{
return vertices[v].adj;
}
\ No newline at end of file
#include <iostream>
#include <utility>
/// <summary>
/// 具有固定长度的UFSet 数组实现
/// 暂时不考虑保存数据的问题 下标就是数据
/// </summary>
/// <typeparam name="T"></typeparam>
class UFSet {
int* data;
int size;
public:
UFSet(int size_);
~UFSet();
UFSet(const UFSet&) = delete;
UFSet(UFSet&& s)noexcept;
UFSet& operator=(const UFSet&) = delete;
UFSet& operator=(UFSet&& s)noexcept;
int find(int x)const;
int find(int x); //带路径折叠
int merge(int x, int y);
};
UFSet::UFSet(int size_):size(size_)
{
data = new int[size];
std::fill(data, data + size, -1);
}
UFSet::~UFSet()
{
if (data)
delete[] data;
data = nullptr;
}
UFSet::UFSet(UFSet&& s) noexcept:
data(s.data),size(s.size)
{
s.size = 0;
s.data = nullptr;
}
UFSet& UFSet::operator=(UFSet&& s) noexcept
{
size = s.size;
data = s.data;
s.size = 0;
s.data = nullptr;
return *this;
}
int UFSet::find(int x) const
{
while (data[x] >= 0)
x = data[x];
return x;
}
//把路径上所有的都折叠上去
int UFSet::find(int x)
{
int root = static_cast<const UFSet*>(this)->find(x);
while (data[x] >= 0) {
x = data[x];
data[x] = root;
}
return root;
}
//不负责折叠路径
//只把y合并到x
//返回新的根节点
int UFSet::merge(int x, int y)
{
int rx = find(x);
int ry = find(y);
data[rx] += data[ry];
data[ry] = rx;
return rx;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment