使用邻接矩阵存储无向图
【题目要求】
完成一个无向图的类,实现无向图的的创建和输出。
【输入输出】
第一行输入顶点的个数n
第二行输入n个顶点的信息,为字符型。
第三行输入边的条数m
下面m行输入边的起点下标,终点下标和权值
第一行输出图的顶点信息
第二行输出图的边的信息,边按照起点下标升序排列,边的起点坐标小于终点坐标,输出一次即可。
【测试数据】
输入:
4
A B C D
4
0 1
0 2
2 3
3 0
输出:
图的顶点有:A B C D
图的边有:A-B A-C A-D C-D
【代码】
/**使用邻接矩阵存储图--有向网*/
#include<iostream>
#include<limits.h>
#define MAX_V_NUM 20 //顶点的最大个数
using namespace std;
/**图类*/
template <class T>
class MGraph
{
private:
T vertex[MAX_V_NUM];//图元素的一维数组
int arc[MAX_V_NUM][MAX_V_NUM];//图的邻接矩阵,二维数组
int vexNum, arcNum;//元素个数,边的个数
public:
MGraph()//构造函数
{
cin >> vexNum;
for (int i = 0; i < vexNum; i++)
{
cin >> vertex[i]; //输入图元素的一维数组
}
for (int i = 0; i < vexNum; i++)
{
for (int j = 0; j < vexNum; j++)
arc[i][j] = 0;
}
cin >> arcNum;
for (int i = 0; i < arcNum; i++)
{
int start, end;
cin >> start >> end;
arc[start][end] = 1;
arc[end][start] = 1;
}
}
~MGraph() {};
void DFSTraverse(int v);
void BFSTraverse(int v);
void printMG()
{
cout << "图的顶点有:";
for (int i = 0; i < vexNum; i++)
cout << vertex[i] << " ";
cout << endl;
cout << "图的边有:";
for (int i = 0; i < vexNum; i++)
{
for (int j = i+1; j < vexNum; j++)
{
if (arc[i][j] == 1)
cout << vertex[i] << "-" << vertex[j]<<" ";
}
}
}
};
int main()
{
MGraph<char> graph;
graph.printMG();
return 0;
}
无向图的基本计算
【题目要求】
采用邻接矩阵存储有无向图后,如何计算图中有多少条边(不直接读arcNum属性)?输入i、j两个顶点的值(不是下标),判断两个顶点i到j是否有边相连?输入任意一个顶点,输出它的度?
【代码】
/**使用邻接矩阵存储--无向图*/
#include<iostream>
#include<limits.h>
#define MAX_V_NUM 20 //顶点的最大个数
using namespace std;
/**图类*/
template <class T>
class MGraph
{
private:
T vertex[MAX_V_NUM];//图元素的一维数组
int arc[MAX_V_NUM][MAX_V_NUM];//图的邻接矩阵,二维数组
int vexNum, arcNum;//元素个数,边的个数
public:
MGraph()
{
cin>>vexNum;
int i,j;
for(i=0;i<vexNum;i++)
{
cin>>vertex[i];//图元素的一维数组
}
for(i=0;i<vexNum;i++)
for(j=0;j<vexNum;j++)
arc[i][j]=0;//初始化邻接矩阵
cin>>arcNum;
for(i=0;i<arcNum;i++)
{
int start,endi;
cin>>start>>endi;
arc[start][endi]=1;//对称矩阵
arc[endi][start]=1;
}
}
~MGraph( ) {};
void DFSTraverse(int v);
void BFSTraverse(int v);
void printMG()
{
cout<<"图的顶点有:";
int i,j;
for(i=0;i<vexNum;i++)
{
cout<<vertex[i]<<" ";
}
cout<<endl;
cout<<"图的边有:";
for(i=0;i<vexNum;i++)//
{
for(j=i+1;j<vexNum;j++)//
{
if(arc[i][j]==1)
{
cout<<vertex[i]<<"-"<<vertex[j]<<" ";
}
}
}
cout<<endl;
}
int computeArcNum();//计算边的条数
bool isConnected(T v1,T v2);//判断两个顶点是否有边相连
int getIndex(T vertex);//获得顶点的下标
int getDegree(T vertex);//求顶点的度
};
template <class T>
/**计算边的条数*/
int MGraph<T>::computeArcNum()
{
int count=0;
int i,j;
for(i=0;i<vexNum;i++)
{
for(j=0;j<vexNum;j++)
{
if(arc[i][j]==1)
count++;
}
}
return count/2;
}
template <class T>
/**获取对应值的下标*/
int MGraph<T>::getIndex(T vertex1)
{
int i;
for(i=0;i<vexNum;i++)
{
if(vertex[i]==vertex1)
{
return i;
}
}
return -1;//找不到对应的顶点
}
template <class T>
/** 判断两个顶点是否连接 */
bool MGraph<T>::isConnected(T v1,T v2)
{
int index1=getIndex(v1);
int index2=getIndex(v2);
if(index1==-1||index2==-1)
{
return false;//如果有一个顶点不存在,返回false
}
return arc[index1][index2]==1;//根据邻接矩阵判断两个顶点是否相连
}
template <class T>
/**求顶点的度*/
int MGraph<T>::getDegree(T vertex)//求度
{
int i;
int index=getIndex(vertex);
if(index==-1)
{
return -1;
}
int degree=0;
for(i=0;i<vexNum;i++)
{
if(arc[index][i]==1)
{
degree++;
}
}
return degree;
}
int main()
{
MGraph<char> graph;
//graph.printMG();
cout<<"The number of edges: "<<graph.computeArcNum()<<endl;
//cout<<"\n判断顶点是否相连,请输入两个顶点的值:";
char v1,v2;
cin>>v1>>v2;
if(graph.isConnected(v1,v2))
cout<<v1<<" and "<<v2<<" is connected."<<endl;
else
cout<<v1<<" and "<<v2<<" is not connected."<<endl;
//cout<<"输出顶点的度,输入一个顶点";
cin>>v1;
cout<<v1<<" degree: "<<graph.getDegree(v1);
return 0;
}
使用邻接表存储有向网
vertex:数据域,存放顶点信息。
firsteArc:指针域,指向边表中第一个结点。
adjvex:邻接点域,边的终点在顶点表中的下标。
nextArc:指针域,指向边表中的下一个结点。
边表还可以有权值域weight
【题目要求】
使用邻接表存储一个有向网,输出图的基本信息。构成链表时可以使用头插法
【输入输出】
第一行输入顶点的个数
第二行输入顶点的内容,为字符型
第三行输入边的条数
下面多行输入每条边的起点下标,终点下标和权值。
第一行输出图的顶点。
第二行输出图的边,输出权值。
【测试数据】
输入:
4
0 1 2 3
4
0 1 2
0 2 5
2 3 8
3 0 7
输出:
图的顶点有:0 1 2 3
图的边有:0-2:[5] 0-1:[2] 2-3:[8] 3-0:[7]
【代码】
#include<iostream>
#define MAX_VERTEX_NUM 20//最大顶点个数
using namespace std;
/**边表的结构体*/
struct ArcNode
{
int adjvex;//邻接点在数组中的位置下标
struct ArcNode* nextArc;//指向下一个邻接点的指针
int weight;//权值,网才有权值
};
/**顶点的结构体*/
template <class T>
struct VNode
{
T vertex;//顶点的数据域
ArcNode* firstArc;//指向邻接点的指针
};
/**邻接表类*/
template <class T>
class ALGraph
{
private:
VNode<T> AdjList[MAX_VERTEX_NUM];//顶点表的数组
int vexNum, arcNum;//记录图中顶点数和边或弧数
public:
ALGraph();//构造函数
~ALGraph() {}; //析构函数
void printALG();//打印函数
void createDN();//构造有向网
int getOutDegreeDN(T vertex);//根据指定的值求出度
int getInDegreeDN(T vertex);//根据指定的值求入度
void setVertex(int index, T value);
void incrementVexNum();
};
template <class T>
ALGraph<T>::ALGraph() {
// 将顶点数和边数初始化为0
vexNum = 0;
arcNum = 0;
// 顶点表的数组初始化
for (int i = 0; i < MAX_VERTEX_NUM; i++) {
AdjList[i].firstArc = NULL;
}
}
// 输出函数
template <class T>
void ALGraph<T>::printALG() {
cout << "图的顶点有:";
// 依次遍历顶点表,输出顶点
for (int i = 0; i < vexNum; i++) {
cout << AdjList[i].vertex << " ";
}
cout << endl;
// 遍历边表
cout << "图的边有:";
for (int i = 0; i < vexNum; i++) {
ArcNode* p = AdjList[i].firstArc; //定义一个p指针,初始化指向顶点表的第一个指向邻接表的指针
// 遍历边表,p不为空的话
while (p) {
cout << AdjList[i].vertex << "-" << AdjList[p->adjvex].vertex << ":[" << p->weight << "] "; //就输出边表对应的数据:起始位置-终点位置:【权值】
p = p->nextArc; //p移到下一位
}
}
cout << endl;
}
// 构建有向图
template <class T>
void ALGraph<T>::createDN() {
int u, v, w;
// 输入起点下标,终点下标,权值
cin >> u >> v >> w;
ArcNode* p = new ArcNode; //定义邻接表的p指针
p->adjvex = v; //传入邻接点在数组中的终点位置下标
p->weight = w; //传入对应的权值
// 头插法插入新的数据
p->nextArc = AdjList[u].firstArc;
AdjList[u].firstArc = p;
arcNum++; //边数增加
}
//更改顶点表的数据域,传入下标和数据
template <class T>
void ALGraph<T>::setVertex(int index, T value) {
if (index >= 0 && index < MAX_VERTEX_NUM) {
AdjList[index].vertex = value;
}
}
//vexNum为私有属性,不能直接访问
template <class T>
void ALGraph<T>::incrementVexNum() {
if (vexNum < MAX_VERTEX_NUM) {
vexNum++;
}
}
int main() {
ALGraph<char> graph;
int n, m;
// 输入顶点的个数
cin >> n;
// 输入顶点
for (int i = 0; i < n; i++) {
char v;
cin >> v;
graph.setVertex(i, v);
graph.incrementVexNum();
}
// 输入边的个数
cin >> m;
// 输入边的起点下标,终点下标和权值。
for (int i = 0; i < m; i++) {
graph.createDN();
}
// 打印输出
graph.printALG();
return 0;
}
构造函数可以像下面这样写,会更简洁。这样大部分输入操作就在构造函数中完成,不用再在主函数中输入,也就不需要
void setVertex(int index, T value);
void incrementVexNum();
这两个函数来传值。
ALGraph()//构造函数
{
vexNum=0;
arcNum=0;
int i;
for(i=0; i<MAX_VERTEX_NUM; i++)
{
AdjList[i].firstArc=NULL;//初始化操作
}
int n, m;
cin >> n;
vexNum=n;
for (int i = 0; i < n; i++)
{
char vertex;
cin >> vertex;
AdjList[i].vertex = vertex;
}
cin >> m;
for (int i = 0; i < m; i++)
{
int u, v, w;
cin >> u >> v >> w;
ArcNode *p = new ArcNode;
p->adjvex = v;
p->weight = w;
p->nextArc = AdjList[u].firstArc;
AdjList[u].firstArc = p;
}
有向网的基本计算
【题目要求】
采用邻接表存储有向网后,如何计算图中有多少条边(不直接读arcNum属性)?输入i、j两个顶点的值(不是下标),判断两个顶点i到j是否有边相连?输入任意一个顶点,输出它的入度和出度?
这里提供了以下函数:
- int getIndex(T vertex);//获得顶点的下标
- int getOutDegreeDN(T vertex);//根据指定的值求出度
- int getInDegreeDN(T vertex);//根据指定的值求入度
- int computeArcNum();//计算边的条数
- bool isConnected(T v1,T v2);//判断两个顶点是否有边相连
【代码】
获得顶点下标
//获取顶点的下标
template <class T>
int ALGraph<T>::getIndex(T vertex) { //传入顶点
for (int i = 0; i < vexNum; i++) { //遍历顶点表
if (AdjList[i].vertex == vertex) { //如果顶点表的数据域与传入要查找的顶点相同的话,就返回此时的下标
return i;
}
}
return -1; //如果没找到,就返回-1
}
根据指定的值求出度
template <class T>
int ALGraph<T>::getOutDegreeDN(T vertex) {
int index = getIndex(vertex);
if (index == -1) { //如果传入的数据不属于顶点表,就返回-1
return -1;
}
int count = 0;
ArcNode* p = AdjList[index].firstArc;
while (p) {
count++;
p = p->nextArc;
}
return count;
}
根据指定的值求入度
template <class T>
int ALGraph<T>::getInDegreeDN(T vertex) {
int count = 0;
for (int i = 0; i < vexNum; i++) {
ArcNode* p = AdjList[i].firstArc;
while (p) {
if (p->adjvex == getIndex(vertex)) {
count++;
}
p = p->nextArc;
}
}
return count;
}
计算边的条数
template <class T>
int ALGraph<T>::computeArcNum() {
int count = 0;
//遍历边表
for (int i = 0; i < vexNum; i++) {
ArcNode* p = AdjList[i].firstArc;
while (p) {
count++;
p = p->nextArc;
}
}
return count;
}
判断两个顶点是否有边相连
template <class T>
bool ALGraph<T>::isConnected(T v1, T v2) {
//获取两个顶点的下标
int index1 = getIndex(v1);
int index2 = getIndex(v2);
if (index1 == -1 || index2 == -1) {
return false; //如果没找到该顶点,就返回假
}
//遍历下标为index1的顶点对应的边表
ArcNode* p = AdjList[index1].firstArc;
while (p) {
if (p->adjvex == index2) { //邻接点在数组中的位置下标等于要找的顶点在数组中的下标,说明能找到这个顶点,所以两个顶点有关联,返回真
return true;
}
p = p->nextArc;
}
return false;
}