C++ 如何用c++;
我想写prims和dijkstra算法来创建一个MST。但是我不知道C++中图形的最佳表示方式是什么。 我可以用两个整数对来表示一条边,例如向量0到1是一对(0,1)C++ 如何用c++;,c++,graph,C++,Graph,我想写prims和dijkstra算法来创建一个MST。但是我不知道C++中图形的最佳表示方式是什么。 我可以用两个整数对来表示一条边,例如向量0到1是一对(0,1) typedef对边; 然后prims函数将得到由边及其权重组成的向量对 void prims(vector<pair<Edge, int>>); void prims(向量); 我认为这种方法不是最好的方法,有人能告诉我什么方法是表示图形的最好方法吗?不久前,我一直在使用Dijkstra在二值图像中查
typedef对边;
然后prims函数将得到由边及其权重组成的向量对
void prims(vector<pair<Edge, int>>);
void prims(向量);
我认为这种方法不是最好的方法,有人能告诉我什么方法是表示图形的最好方法吗?不久前,我一直在使用Dijkstra在二值图像中查找路径。我将图形表示为结构
GraphNodes
的向量,该结构包含连接的向量,该向量包含节点到其他节点的所有连接。每个连接都有其距离属性,即边的权重。以下是我使用的两个结构:
//forward declaration
struct GraphNode;
struct Connection {
Connection() : distance(1) { };
Connection(GraphNode* ptr, double distance) : ptr(ptr), distance(distance) { };
bool operator==(const Connection &other) const;
GraphNode* ptr;
double distance;
};
struct GraphNode {
GraphNode() : connections(8), predecessor(NULL), distance(-1) { };
cv::Point point;
double distance;
GraphNode* predecessor;
std::vector<Connection> connections;
};
bool Connection::operator==(const Connection &other) const {
return ptr == other.ptr && distance == other.distance;
}
如您所见,有一个集合unusedNodes
,其中包含迄今为止所有未使用的节点。它只包含图形节点上的指针。实际的图形表示在向量中。拥有一个集合的优点是,它总是根据某个标准进行排序。我实现了自己的sorterGraphDistanceSorter
,它根据Dijkstra算法的距离标准对图形节点进行排序。这样,我只需从集合中选择第一个节点,并知道它是距离最小的节点:
struct GraphDistanceSorter {
bool operator() (const GraphNode* lhs, const GraphNode* rhs) const;
};
bool GraphDistanceSorter::operator() (const GraphNode* lhs, const GraphNode* rhs) const {
if (lhs->distance == rhs->distance) {
return lhs < rhs;
} else {
if (lhs->distance != -1 && rhs->distance != -1) {
if (lhs->distance != rhs->distance) {
return lhs->distance < rhs->distance;
}
} else if (lhs->distance != -1 && rhs->distance == -1) {
return true;
}
return false;
}
}
结构图距离分类器{
布尔运算符()(常量图形节点*lhs,常量图形节点*rhs)常量;
};
bool GraphDistanceSorter::operator()(常量GraphNode*lhs,常量GraphNode*rhs)常量{
如果(左侧->距离==右侧->距离){
返回左侧<右侧;
}否则{
如果(左侧->距离!=-1和右侧->距离!=-1){
如果(左侧->距离!=右侧->距离){
返回左侧->距离<右侧->距离;
}
}否则如果(左侧->距离!=-1&&rhs->距离==-1){
返回true;
}
返回false;
}
}
在理论计算机科学中学习的两种主要图形表示方法是和
如下图所示,邻接矩阵是一个n*n矩阵,[i][j]表示节点i和节点j之间的边,因此,如果是加权图,它可以是整数,而不是未加权图的布尔值
另一方面,邻接列表是一组链表(确切地说是n集),第i集正好有我连接的节点。
在这种情况下,您将需要一些额外的方法来保存边距离,例如,您可以按照以下方式构建自己的类边
class Edge
{
int destination, length;
Edge* next = 0;
}
并将其用于链接列表。我是如何习惯于std::vector a[N]
来定义对列表和a[I][j]。首先
将是节点I和a[I][j的第j个邻居。其次
它们之间的边的长度。
对于无向图,也可以将i添加到j邻域。
因此,它也是一种灵活的图形表示方法
现在让我们谈谈复杂性,我会尽量让它简单:
我们有n个列表,每个列表都有#(节点i外的边)
所以总数是这些数的总和,也就是边的总数。
这意味着位置复杂性是O(E),与邻接矩阵中的O(n^2)相比,稀疏图中的位置复杂性最多为5*n。(我们需要一个线性因子E来表示它)。
现在让我们考虑访问NOD X的所有邻居:
在邻接矩阵中,我们将遍历整个x行,如果它不是0,那么那里有一条边是O(N)。
在邻接列表中,x的邻接数可以达到O(N)。
但是,如果我们访问所有节点的所有邻居(在Dijkstra中更新dis数组时就是这种情况),您将需要在邻接列表中访问n个元素n次,这也是O(n^2)时间复杂度,而在邻接列表中,它正好是邻居数目的和-同样是E。这意味着我们还需要O(E)访问所有边缘的所有邻居。
sind通常在输入中给出所有边O(E)将作为计算时间通过,但是O(N^2)对于N>N>>E的约束将是一个高复杂性;
for(int i=0;i>x>>y>>z;
//如果从1开始,则用x和y替换1
图[x]。推回(std::生成(y,z)对);
逆[y]。推回(std::生成_对(x,z));
未加权[x]。推回(y);
无向加权[x]。向后推(y);
无向加权[y]。向后推(x);
}
返回0;
}
表示图形的简单形式(查找顶点的邻域和度)
#包括
/**表示C++语言中的图**
使用名称空间std;
int main(){
也许你想考虑使用<代码> STD::tuple < /Case> s三个int,而不是嵌套对,但是我要说的是,即使你不是这个世界上最好的一个,你也可以理解一个解决方案。当你对它有更多的经验时,你总是可以改进它。表示一个连接,例如3->4,5->3,…是的,但每个对/边都有权重。好吧,我想问一下,在哪种意义上最好。内存使用?更可读?最快的插入?最快的导航?不幸的是,你不能拥有所有这些。可读性,良好的语法和常识。
struct GraphDistanceSorter {
bool operator() (const GraphNode* lhs, const GraphNode* rhs) const;
};
bool GraphDistanceSorter::operator() (const GraphNode* lhs, const GraphNode* rhs) const {
if (lhs->distance == rhs->distance) {
return lhs < rhs;
} else {
if (lhs->distance != -1 && rhs->distance != -1) {
if (lhs->distance != rhs->distance) {
return lhs->distance < rhs->distance;
}
} else if (lhs->distance != -1 && rhs->distance == -1) {
return true;
}
return false;
}
}
class Edge
{
int destination, length;
Edge* next = 0;
}
#include<iostream>
#include<vector>
int main(){
const int N = 5;
int n, e;
std::vector<std::pair<int, int>> graph[N], inverse[N];
std::vector<int> unweighted[N], undirectedUnweighted[N];
std::cin >> n >> e;
for(int i = 0; i < e; i++)
{
int x, y, z;//z is length of edge
std::cin >> x >> y >> z;
//substitute 1 from x, y if they starts from 1
graph[x].push_back(std::make_pair(y, z));
inverse[y].push_back(std::make_pair(x, z));
unweighted[x].push_back(y);
undirectedUnweighted[x].push_back(y);
undirectedUnweighted[y].push_back(x);
}
return 0;
}
#include<iostream>
/** Representing graphs in c++ programming language */
using namespace std;
int main() {
cout << "\033[1;33mNote: if there are no neighbourhood between vertices write '-' symbol!\033[0m\n"<<endl;
int number_of_vertices;
cout<<"\033[1;32mPlease enter number of vertices: \033[0m";
cin>>number_of_vertices;
int max_num_of_neighbours;
cout<<"\033[1;32mPlease enter maximum number of neighbours: \033[0m";
cin>>max_num_of_neighbours;
char array[number_of_vertices][max_num_of_neighbours];
char vertices[number_of_vertices];
cout<<"\033[1;33mPlease sign vertices with lowercase alphabet letters: \033[0m"<<endl;
for(int i = 0; i < number_of_vertices; i ++) {
cout<<(i+1)<<" = ";
cin>>vertices[i];
}
for(int i = 0; i < number_of_vertices; cout<<endl, i ++) {
cout<<"\033[1;32mPlease enter neighbours for \033[0m"<<vertices[i]<<" --> ";
for(int j = 0; j < max_num_of_neighbours; j ++) {
cin>>array[i][j];
}
}
for(int i = 0; i < number_of_vertices; cout<<endl, i ++) {
cout<<"\033[1;34mNeighbours for \033[0m"<<"\033[1;35m"<<vertices[i]<<"\033[0m"<<" --> ";
int deg = 0;
for(int j = 0; j < max_num_of_neighbours; j ++) {
if(array[i][j] != '-') {
deg ++;
}
if(array[i][j] == '-') {
cout<<"\033[1;31m"<<array[i][j]<<"\033[0m"<<"\t";
} else {
cout<<"\033[1;32m"<<array[i][j]<<"\033[0m"<<"\t";
}
}
cout<<"\033[1;36m"<<"deg["<<"\033[0m"<<"\033[1;35m"<<vertices[i]<<"\033[0m"<<"\033[1;36m"<<"] = "<<"\033[0m"<<deg;
}
cout<<endl<<"\033[1;33mRemember that '\033[1;31m-\033[0m\033[1;33m' shows when two vertices aren't adjacent!\033[0m"<<endl;
}