Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Xingyue MA
xepTemplateLibrary
Commits
8a83c344
Commit
8a83c344
authored
Oct 06, 2021
by
xep
Browse files
graph v2
parent
f6f7815b
Changes
2
Hide whitespace changes
Inline
Side-by-side
xtl_graph_v2.hpp
0 → 100644
View file @
8a83c344
#pragma once
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <deque>
#include <memory>
#include <type_traits>
namespace
xtl
{
namespace
detail
{
struct
_Edge_base
;
struct
_Vertex_base
{
std
::
shared_ptr
<
_Edge_base
>
in_edge
,
out_edge
;
// 入边链表
_Vertex_base
()
=
default
;
int
in_degree
()
const
;
int
out_degree
()
const
;
};
struct
_Edge_base
{
std
::
weak_ptr
<
_Vertex_base
>
from
,
to
;
std
::
shared_ptr
<
_Edge_base
>
next_out
,
next_in
;
// 下一出边
_Edge_base
(
const
std
::
weak_ptr
<
_Vertex_base
>&
from
,
const
std
::
weak_ptr
<
_Vertex_base
>&
to
)
:
from
(
from
),
to
(
to
){}
};
template
<
typename
_VData
>
struct
_Vertex
:
public
_Vertex_base
{
_VData
data
;
_Vertex
(
const
_VData
&
data
)
:
data
(
data
){}
_Vertex
(
_VData
&&
data
)
:
data
(
std
::
forward
<
_VData
>
(
data
)){}
template
<
typename
_Ty
=
_VData
,
std
::
enable_if_t
<
std
::
is_default_constructible_v
<
_Ty
>
>>
_Vertex
()
:
data
(){}
template
<
typename
...
Args
>
_Vertex
(
Args
&&
...
args
)
:
data
(
std
::
forward
<
Args
>
(
args
)...){}
};
template
<
>
struct
_Vertex
<
void
>
:
public
_Vertex_base
{
_Vertex
()
=
default
;
};
template
<
typename
_EData
>
struct
_Edge
:
public
_Edge_base
{
_EData
data
;
_Edge
(
const
std
::
weak_ptr
<
_Vertex_base
>&
from
,
const
std
::
weak_ptr
<
_Vertex_base
>&
to
,
const
_EData
&
data
)
:
_Edge_base
(
from
,
to
),
data
(
data
){}
_Edge
(
const
std
::
weak_ptr
<
_Vertex_base
>&
from
,
const
std
::
weak_ptr
<
_Vertex_base
>&
to
,
_EData
&&
data
)
:
_Edge_base
(
from
,
to
),
data
(
std
::
forward
<
_EData
>
(
data
)){}
template
<
typename
_Ty
=
_EData
,
std
::
enable_if_t
<
std
::
is_default_constructible_v
<
_Ty
>
>>
_Edge
(
const
std
::
weak_ptr
<
_Vertex_base
>&
from
,
const
std
::
weak_ptr
<
_Vertex_base
>&
to
)
:
_Edge_base
(
from
,
to
),
data
(){}
template
<
typename
...
Args
>
_Edge
(
const
std
::
weak_ptr
<
_Vertex_base
>&
from
,
const
std
::
weak_ptr
<
_Vertex_base
>&
to
,
Args
&&
...
args
)
:
_Edge_base
(
from
,
to
),
data
(
std
::
forward
<
Args
>
(
args
)...){}
};
template
<
>
struct
_Edge
<
void
>
:
public
_Edge_base
{
using
_Edge_base
::
_Edge_base
;
};
int
_Vertex_base
::
in_degree
()
const
{
int
res
=
0
;
auto
e
=
in_edge
;
while
(
e
)
{
e
=
e
->
next_in
;
res
++
;
}
return
res
;
}
int
_Vertex_base
::
out_degree
()
const
{
int
res
=
0
;
auto
e
=
out_edge
;
while
(
e
)
{
e
=
e
->
next_out
;
res
++
;
}
return
res
;
}
}
/**
* 多重邻接表实现有向图。使用映射结构来保存结点。
* 按STL风格命名
*/
template
<
typename
_Key
,
typename
_VData
,
typename
_EData
>
class
di_graph
{
public:
using
key_type
=
_Key
;
using
vertex_data_type
=
_VData
;
using
edge_data_type
=
_EData
;
using
vertex
=
detail
::
_Vertex
<
_VData
>
;
using
edge
=
detail
::
_Edge
<
_EData
>
;
private:
std
::
map
<
key_type
,
std
::
shared_ptr
<
vertex
>>
_vertices
;
public:
di_graph
()
=
default
;
size_t
size
()
const
{
return
_vertices
.
size
();
}
bool
empty
()
const
{
return
_vertices
.
empty
();
}
auto
&
vertices
()
{
return
_vertices
;
}
const
auto
&
vertices
()
const
{
return
_vertices
;
}
std
::
shared_ptr
<
vertex
>
find_vertex
(
const
key_type
&
key
)
{
if
(
auto
itr
=
_vertices
.
find
(
key
);
itr
!=
_vertices
.
end
())
return
itr
->
second
;
else
return
nullptr
;
}
std
::
shared_ptr
<
const
vertex
>
find_vertex
(
const
key_type
&
key
)
const
{
if
(
auto
itr
=
_vertices
.
find
(
key
);
itr
!=
_vertices
.
end
())
return
itr
->
second
;
else
return
nullptr
;
}
template
<
typename
_Ty
=
_VData
,
typename
=
std
::
enable_if_t
<!
std
::
is_void_v
<
_Ty
>
>>
std
::
shared_ptr
<
vertex
>
insert_vertex
(
const
key_type
&
key
,
const
_Ty
&
data
)
{
auto
[
itr
,
_
]
=
_vertices
.
insert
({
key
,
std
::
make_shared
<
vertex
>
(
data
)
});
return
itr
->
second
;
}
template
<
typename
_Ty
=
_VData
,
typename
=
std
::
enable_if_t
<
std
::
is_default_constructible_v
<
_Ty
>
||
std
::
is_void_v
<
_Ty
>>>
std
::
shared_ptr
<
vertex
>
insert_vertex
(
const
key_type
&
key
)
{
auto
[
itr
,
_
]
=
_vertices
.
insert
({
key
,
std
::
make_shared
<
vertex
>
()
});
return
itr
->
second
;
}
template
<
typename
_K
,
typename
...
Args
>
std
::
shared_ptr
<
vertex
>
emplace_vertex
(
_K
&&
key
,
Args
&&
...
args
)
{
auto
[
itr
,
_
]
=
_vertices
.
emplace
(
std
::
forward
<
_K
>
(
key
),
std
::
make_shared
<
vertex
>
(
std
::
forward
<
Args
>
(
args
)...));
return
itr
->
second
;
}
template
<
typename
_Ty
=
_EData
,
typename
=
std
::
enable_if_t
<!
std
::
is_void_v
<
_Ty
>
>>
std
::
shared_ptr
<
edge
>
insert_edge
(
std
::
shared_ptr
<
vertex
>
from
,
std
::
shared_ptr
<
vertex
>
to
,
const
_Ty
&
data
)
{
auto
e
=
std
::
make_shared
<
edge
>
(
from
,
to
,
data
);
e
->
next_in
=
to
->
in_edge
;
to
->
in_edge
=
e
;
e
->
next_out
=
from
->
out_edge
;
from
->
out_edge
=
e
;
return
e
;
}
template
<
typename
_Ty
=
_EData
,
typename
=
std
::
enable_if_t
<!
std
::
is_void_v
<
_Ty
>
>>
std
::
shared_ptr
<
edge
>
insert_edge
(
const
std
::
shared_ptr
<
vertex
>&
from
,
const
std
::
shared_ptr
<
vertex
>&
to
,
_Ty
&&
data
)
{
auto
e
=
std
::
make_shared
<
edge
>
(
from
,
to
,
std
::
forward
<
_EData
>
(
data
));
e
->
next_in
=
to
->
in_edge
;
to
->
in_edge
=
e
;
e
->
next_out
=
from
->
out_edge
;
from
->
out_edge
=
e
;
return
e
;
}
template
<
typename
...
Args
>
std
::
shared_ptr
<
edge
>
emplace_edge
(
const
std
::
shared_ptr
<
vertex
>&
from
,
const
std
::
shared_ptr
<
vertex
>&
to
,
Args
&&
...
args
)
{
auto
e
=
std
::
make_shared
<
edge
>
(
from
,
to
,
std
::
forward
<
Args
>
(
args
)...);
e
->
next_in
=
to
->
in_edge
;
to
->
in_edge
=
e
;
e
->
next_out
=
from
->
out_edge
;
from
->
out_edge
=
e
;
return
e
;
}
void
clear
()
{
_vertices
.
clear
();
}
template
<
typename
_Val
>
struct
sssp_ret_t
{
std
::
unordered_map
<
std
::
shared_ptr
<
const
vertex
>
,
_Val
>
distance
;
std
::
unordered_map
<
std
::
shared_ptr
<
const
vertex
>
,
std
::
shared_ptr
<
const
edge
>>
path
;
};
/**
* 2021.09.24 尝试第二个版本
* 将标记完成的集合si改成待定序列的集合,避免反复查找si
*/
template
<
typename
_Func
,
typename
_Val
=
decltype
(
std
::
declval
<
_Func
>()(
std
::
declval
<
_EData
>
())),
typename
=
std
::
enable_if_t
<
std
::
is_arithmetic_v
<
_Val
>>
>
sssp_ret_t
<
_Val
>
sssp
(
std
::
shared_ptr
<
const
vertex
>
source
,
_Func
func
)
const
;
/**
* 2021.09.24 尝试第二个版本
* 将标记完成的集合si改成待定序列的集合,避免反复查找si
*/
template
<
typename
_Val
=
_EData
,
typename
=
std
::
enable_if_t
<
std
::
is_arithmetic_v
<
_Val
>
>>
sssp_ret_t
<
_Val
>
sssp
(
std
::
shared_ptr
<
const
vertex
>
source
)
const
;
using
path_t
=
std
::
deque
<
std
::
shared_ptr
<
const
edge
>>
;
/**
* 由sssp计算结果给出路径,以边的序列表示。
* 如果不可达或者source, target一样,返回空
*/
template
<
typename
_Val
>
std
::
deque
<
std
::
shared_ptr
<
const
edge
>>
dump_path
(
const
std
::
shared_ptr
<
const
vertex
>&
source
,
const
std
::
shared_ptr
<
const
vertex
>&
target
,
const
sssp_ret_t
<
_Val
>&
res
)
const
{
if
(
auto
itr
=
res
.
distance
.
find
(
target
);
itr
==
res
.
distance
.
end
())
{
return
{};
}
std
::
deque
<
std
::
shared_ptr
<
const
edge
>>
path
;
std
::
shared_ptr
<
const
vertex
>
cur
=
target
;
while
(
cur
!=
source
)
{
if
(
auto
itr
=
res
.
path
.
find
(
cur
);
itr
!=
res
.
path
.
end
())
{
// 找到上一步的路径
path
.
emplace_front
(
itr
->
second
);
cur
=
itr
->
second
->
from
.
lock
();
}
else
{
break
;
}
}
if
(
cur
==
source
)
{
// 成功找到路径
return
path
;
}
else
{
return
{};
}
}
private:
template
<
typename
_Val
>
std
::
shared_ptr
<
const
vertex
>
get_min_dist
(
const
std
::
unordered_map
<
std
::
shared_ptr
<
const
vertex
>
,
_Val
>&
choice
,
_Val
MAX
)
const
{
_Val
curmin
=
MAX
;
std
::
shared_ptr
<
const
vertex
>
cur
{};
for
(
auto
p
=
choice
.
begin
();
p
!=
choice
.
end
();
++
p
)
{
if
(
p
->
second
<
curmin
)
{
curmin
=
p
->
second
;
cur
=
p
->
first
;
}
}
return
cur
;
}
};
template
<
typename
_Key
,
typename
_VData
,
typename
_EData
>
template
<
typename
_Func
,
typename
_Val
,
typename
>
typename
di_graph
<
_Key
,
_VData
,
_EData
>::
template
sssp_ret_t
<
_Val
>
di_graph
<
_Key
,
_VData
,
_EData
>::
sssp
(
std
::
shared_ptr
<
const
vertex
>
source
,
_Func
func
)
const
{
constexpr
_Val
MAX
=
std
::
numeric_limits
<
_Val
>::
max
()
-
1
;
sssp_ret_t
<
_Val
>
ret
{};
// 候选项:可达但还没被固定下来的结点及其距离
std
::
unordered_map
<
std
::
shared_ptr
<
const
vertex
>
,
_Val
>
choice
;
ret
.
distance
.
emplace
(
source
,
(
_Val
)
0
);
choice
.
emplace
(
source
,
(
_Val
)
0
);
// 注:数值为空表示不可达/无穷大
for
(
int
i
=
0
;
i
<
size
();
i
++
)
{
auto
mi
=
get_min_dist
<
_Val
>
(
choice
,
MAX
);
if
(
mi
)
{
// 此节点被固定
for
(
auto
e
=
mi
->
out_edge
;
e
;
e
=
e
->
next_out
)
{
auto
mj
=
e
->
to
.
lock
();
_Val
dnew
=
ret
.
distance
.
at
(
mi
)
+
func
(
e
->
data
);
if
(
auto
itr
=
ret
.
distance
.
find
(
mj
);
itr
==
ret
.
distance
.
end
()
||
dnew
<
itr
->
second
)
{
// 原来无路径,或是新的路径更短
choice
[
mj
]
=
dnew
;
ret
.
distance
[
mj
]
=
dnew
;
ret
.
path
[
mj
]
=
e
;
}
}
choice
.
erase
(
mi
);
}
else
{
// 没有可达的了
break
;
}
}
return
ret
;
}
template
<
typename
_Key
,
typename
_VData
,
typename
_EData
>
template
<
typename
_Val
,
typename
>
typename
di_graph
<
_Key
,
_VData
,
_EData
>::
template
sssp_ret_t
<
_Val
>
di_graph
<
_Key
,
_VData
,
_EData
>::
sssp
(
std
::
shared_ptr
<
const
vertex
>
source
)
const
{
constexpr
_Val
MAX
=
std
::
numeric_limits
<
_Val
>::
max
()
-
1
;
sssp_ret_t
<
_Val
>
ret
{};
// 候选项:可达但还没被固定下来的结点及其距离
std
::
unordered_map
<
std
::
shared_ptr
<
const
vertex
>
,
_Val
>
choice
;
ret
.
distance
.
emplace
(
source
,
(
_Val
)
0
);
choice
.
emplace
(
source
,
(
_Val
)
0
);
// 注:数值为空表示不可达/无穷大
for
(
int
i
=
0
;
i
<
size
();
i
++
)
{
auto
mi
=
get_min_dist
<
_Val
>
(
choice
,
MAX
);
if
(
mi
)
{
// 此节点被固定
for
(
auto
e
=
mi
->
out_edge
;
e
;
e
=
e
->
next_out
)
{
auto
mj
=
e
->
to
.
lock
();
_Val
dnew
=
ret
.
distance
.
at
(
mi
)
+
e
->
data
;
if
(
auto
itr
=
ret
.
distance
.
find
(
mj
);
itr
==
ret
.
distance
.
end
()
||
dnew
<
itr
->
second
)
{
// 原来无路径,或是新的路径更短
choice
[
mj
]
=
dnew
;
ret
.
distance
[
mj
]
=
dnew
;
ret
.
path
[
mj
]
=
e
;
}
}
choice
.
erase
(
mi
);
}
else
{
// 没有可达的了
break
;
}
}
return
ret
;
}
}
xtl_index_graph.hpp
0 → 100644
View file @
8a83c344
#include <memory>
#include <vector>
#include <type_traits>
#include <cstdio>
#include <limits>
namespace
xtl
{
/**
* The index-based di-graph, implemented with RAII
*/
template
<
typename
_VData
,
typename
_EData
>
class
di_igraph
{
public:
using
vertex_data_type
=
_VData
;
using
edge_data_type
=
_EData
;
using
index_type
=
size_t
;
struct
edge
;
struct
vertex
{
_VData
data
;
std
::
shared_ptr
<
edge
>
in_edge
,
out_edge
;
template
<
typename
_Ty
=
_VData
,
typename
=
std
::
enable_if_t
<
std
::
is_default_constructible_v
<
_Ty
>
>>
vertex
(){}
vertex
(
const
_VData
&
data
)
:
data
(
data
){}
vertex
(
_VData
&&
data
)
:
data
(
std
::
forward
<
_VData
>
(
data
)){}
template
<
typename
...
Args
>
vertex
(
Args
&&
...
args
)
:
data
(
std
::
forward
<
Args
>
(
args
)...){}
size_t
in_degree
()
const
;
size_t
out_degree
()
const
;
};
struct
edge
{
_EData
data
;
index_type
from
,
to
;
std
::
shared_ptr
<
edge
>
next_in
,
next_out
;
template
<
typename
_Ty
=
_EData
,
typename
=
std
::
enable_if_t
<
std
::
is_default_constructible_v
<
_Ty
>
>>
edge
(
index_type
from
,
index_type
to
)
:
from
(
from
),
to
(
to
){}
edge
(
index_type
from
,
index_type
to
,
const
_EData
&
data
)
:
from
(
from
),
to
(
to
),
data
(
data
){}
edge
(
index_type
from
,
index_type
to
,
_EData
&&
data
)
:
from
(
from
),
to
(
to
),
data
(
std
::
forward
<
_EData
>
(
data
)){}
template
<
typename
...
Args
>
edge
(
index_type
from
,
index_type
to
,
Args
&&
...
args
)
:
data
(
std
::
forward
<
Args
>
(
args
)...),
from
(
from
),
to
(
to
){}
};
private:
std
::
vector
<
std
::
shared_ptr
<
vertex
>>
_vertices
;
static
constexpr
index_type
INVALID_INDEX
=
std
::
numeric_limits
<
index_type
>::
max
();
public:
di_igraph
()
=
default
;
size_t
size
()
const
{
return
_vertices
.
size
();
}
bool
empty
()
const
{
return
_vertices
.
empty
();
}
auto
&
vertices
()
{
return
_vertices
;
}
const
auto
&
vertices
()
const
{
return
_vertices
;
}
void
clear
()
{
_vertices
.
clear
();
}
template
<
typename
_Ty
=
_VData
,
typename
=
std
::
enable_if_t
<
std
::
is_default_constructible_v
<
_Ty
>
>>
void
resize
(
size_t
s
)
{
if
(
s
<=
size
())
_vertices
.
resize
(
s
);
else
{
auto
old_size
=
size
();
for
(
int
i
=
0
;
i
<
(
s
-
old_size
);
i
++
)
{
emplace_vertex
();
}
}
}
std
::
shared_ptr
<
vertex
>
vertex_at
(
index_type
i
)
{
return
_vertices
.
at
(
i
);
}
std
::
shared_ptr
<
const
vertex
>
vertex_at
(
index_type
i
)
const
{
return
_vertices
.
at
(
i
);
}
std
::
shared_ptr
<
vertex
>
push_vertex
(
const
_VData
&
data
)
{
auto
v
=
std
::
make_shared
<
vertex
>
(
data
);
_vertices
.
push_back
(
v
);
return
v
;
}
std
::
shared_ptr
<
vertex
>
push_vertex
(
_VData
&&
data
)
{
auto
v
=
std
::
make_shared
<
vertex
>
(
std
::
forward
<
_VData
>
(
data
));
_vertices
.
push_back
(
v
);
return
v
;
}
template
<
typename
...
Args
>
std
::
shared_ptr
<
vertex
>
emplace_vertex
(
Args
&&
...
args
)
{
auto
v
=
std
::
make_shared
<
vertex
>
(
std
::
forward
<
Args
>
(
args
)...);
_vertices
.
emplace_back
(
v
);
return
v
;
}
std
::
shared_ptr
<
edge
>
insert_edge
(
index_type
from_i
,
index_type
to_i
,
const
_EData
&
data
)
{
auto
e
=
std
::
make_shared
<
edge
>
(
from_i
,
to_i
,
data
);
link_new_edge
(
from_i
,
to_i
,
e
);
return
e
;
}
std
::
shared_ptr
<
edge
>
insert_edge
(
index_type
from_i
,
index_type
to_i
,
_EData
&&
data
)
{
auto
e
=
std
::
make_shared
<
edge
>
(
from_i
,
to_i
,
std
::
forward
<
_EData
>
(
data
));
link_new_edge
(
from_i
,
to_i
,
e
);
return
e
;
}
template
<
typename
...
Args
>
std
::
shared_ptr
<
edge
>
emplace_edge
(
index_type
from_i
,
index_type
to_i
,
Args
&&
...
args
)
{
auto
e
=
std
::
make_shared
<
edge
>
(
from_i
,
to_i
,
std
::
forward
<
Args
>
(
args
)...);
link_new_edge
(
from_i
,
to_i
,
e
);
return
e
;
}
template
<
typename
_Val
>
struct
sssp_ret_t
{
std
::
vector
<
_Val
>
distance
;
//std::vector<index_type> path;
//sssp_ret_t(size_t s):distance(s,std::numeric_limits<_Val>::max()),
// path(s, INVALID_INDEX) {}
sssp_ret_t
(
size_t
s
)
:
distance
(
s
,
std
::
numeric_limits
<
_Val
>::
max
()){}
};
template
<
typename
_Val
=
_EData
,
typename
=
std
::
enable_if_t
<
std
::
is_arithmetic_v
<
_Val
>
>>
sssp_ret_t
<
_Val
>
sssp
(
index_type
source
)
const
{
sssp_ret_t
<
_Val
>
ret
(
size
());
std
::
vector
<
bool
>
si
(
size
(),
false
);
// 起始点
ret
.
distance
[
source
]
=
0
;
for
(
int
i
=
0
;
i
<
size
();
i
++
)
{
index_type
mi
=
get_min_dist
(
ret
,
si
);
if
(
mi
!=
INVALID_INDEX
)
{
si
[
mi
]
=
true
;
std
::
shared_ptr
<
const
vertex
>
vi
=
vertex_at
(
mi
);
for
(
auto
e
=
vi
->
out_edge
;
e
;
e
=
e
->
next_out
)
{
index_type
mj
=
e
->
to
;
if
(
ret
.
distance
.
at
(
mi
)
+
e
->
data
<
ret
.
distance
.
at
(
mj
))
{
ret
.
distance
[
mj
]
=
ret
.
distance
.
at
(
mi
)
+
e
->
data
;
//ret.path[mj] = mi;
}
}
}
else
break
;
}
return
ret
;
}
private:
void
link_new_edge
(
index_type
from_i
,
index_type
to_i
,
const
std
::
shared_ptr
<
edge
>&
e
)
{
auto
from
=
vertex_at
(
from_i
),
to
=
vertex_at
(
to_i
);
e
->
next_in
=
to
->
in_edge
;
to
->
in_edge
=
e
;
e
->
next_out
=
from
->
out_edge
;
from
->
out_edge
=
e
;
}
template
<
typename
_Val
>
index_type
get_min_dist
(
const
sssp_ret_t
<
_Val
>&
ret
,
const
std
::
vector
<
bool
>&
si
)
const
{
index_type
cur
=
INVALID_INDEX
;
_Val
curmin
=
std
::
numeric_limits
<
_Val
>::
max
();
for
(
int
i
=
0
;
i
<
size
();
i
++
)
{
if
(
!
si
.
at
(
i
))
{
if
(
ret
.
distance
.
at
(
i
)
<
curmin
)
{
curmin
=
ret
.
distance
.
at
(
i
);
cur
=
i
;
}
}
}
return
cur
;
}
};
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment