图是一种非常常见的数学模型。图在各种应用中都有非常重要的作用
我们今天要介绍的图叫做无向图,在无向图中,边仅仅起到链接两个顶点的作用。这是一种简单的图模型。
术语解释:
- 自环:一条链接一个顶点与他自身的边
- 平行边(无向图):两条及以上关联同一对顶点的无向边
- 多重图:有平行边的图
- 简单图:无平行边的图
- 度数(度):点作为边端点的次数
//邻接矩阵法构造无向图
class graph
{
private:
int v; //顶点数
int e; //边数
std::vector<std::vector<int>> adj;
public:
graph(int v)
{
this->v = v;
this->e = 0;
adj.resize(v);
}
int numv()
{
return this->v;
}
int nume()
{
return e;
}
void add_edge(int v, int w) //这个插入方法还不够健壮,如果输入的参数比v要大会出错
{
/*
if(v<0||v>this->v)
{
printf("%a");
return;
}
if(w<0||w>this->v)
{
printf("%a");
return;
}
*/
adj[v].push_back(w);
adj[w].push_back(v);
//无向图,所以两个顶点都需要处理
std::unique(adj.begin(), adj.end());
e++;
}
std::vector<int> *iterator(int v) //返回一个指向对应节点的数组的指针
{
return &adj[v];
}
int degree(int v) //返回度数
{
int degree = 0;
for (auto w : adj[v])
{
degree++;
}
return degree;
}
int max_degree() //获取最大度
{
int max = 0;
for (unsigned int i=0;i<adj.size();i++)
{
if (degree(i) > max)
max = degree(i);
}
return max;
}
int selfloop_num() //返回自反顶点的数量
{
int count = 0;
for (int i = 0; i < v; i++)
{
for (unsigned int j = 0; j < adj[i].size(); j++)
{
if (i == j)
{
count++;
break;
}
}
}
return count;
}
std::string tostring() //获取矩阵信息的字符串
{
std::string s;
s = std::to_string(v) + " verticers" + std::to_string(e) + " edges\n";
for (unsigned int i=0;i<adj.size();i++)
{
s += std::to_string(i) + ":";
for (auto j:adj[i])
{
s += std::to_string(j) + " ";
}
s += "\n";
}
return s;
}
};
学过离散数学的读者可能还记得图邻接矩阵的定义,所以上述代码构造图的方式与我们当初接触的邻接矩阵是有区别的。对于这种方式,其优势是占用内存小,缺点则是相比之下更慢。
我个人更偏向第二种,但是此处书中貌似使用的是第一种。
运行结果