1.图的存储类型
顺序存储-邻接矩阵
链式存储-邻接表
9:19
2.用邻接矩阵存储的方式表示无向图的结构
2.1 邻接矩阵
图的邻接矩阵存储方式是用两个数组来表示图。
一个数组存储图中的顶点信息;
一个二维数组(邻接矩阵)存储图中的边或弧的信息.
设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为:
2.2 以邻接矩阵存储无向图的设计
2.3 无向图以顺序存储方式构建的代码
// vertex 英[ˈvɜːteks] 美[ˈvɜːrteks]n.(三角形或锥形的)角顶; 顶点; 至高点;
#include <iostream>
#include <stack>
#include <queue>
#include <cstring>
// int (*p)[10]
// int *p[10]
using namespace std;
#define MaxVertex 50
typedef char VertexInfo[9]; // VertexInfo是一个char[9]这种类型的字符数组
struct Graph{
// 顶点数组,存储顶点的名字,等价于vectex[MaxVertex][VertexInfo],最多存放MaxVertex个顶点
VertexInfo vertex[MaxVertex];
// 边的数组,二维矩阵
int edge[MaxVertex][MaxVertex];
// 顶点的个数
int vertexNum;
// 边的条数
int edgeNum;
};
// 求用户输入的顶点在顶点数组中的位置
int LocalVertex(Graph &g,VertexInfo v)
{
// 遍历顶点数组
for(int i = 0; i < g.vertexNum ; ++i)
{
if(strcmp(v,g.vertex[i]) == 0)
{
// 找到了,返回元素的下标
return i;
}
}
// 没找到
return -1;
}
// 构建一个图
void CreateGraph(Graph &g)
{
cout << "请输入图的顶点个数和边的个数: 顶点,边" << endl;
cin >> g.vertexNum >> g.edgeNum;
cout << "请输入" << g.vertexNum <<"个顶点的名字" << endl;
int i = 0;
for(i = 0; i < g.vertexNum; ++i)
{
cin >> g.vertex[i];
}
// 初始化所有边都不存在
for(i = 0; i< g.vertexNum ; ++i)
{
for(int j = 0; j < g.vertexNum ; ++j)
{
g.edge[i][j] = 0;
}
}
cout << "请输入" << g.edgeNum << "条边的情况,顶点1,顶点2" << endl;
VertexInfo v1,v2;
for(int i = 0; i < g.edgeNum; ++i)
{
cin >> v1 >> v2;
// 求用户输入的顶点在顶点数组中的位置
int m = LocalVertex(g,v1); // 获取v1在二维数组中的位置
int n = LocalVertex(g,v2); // 获取v2在二维数组中的位置
// 边对应的认为数组赋值
g.edge[m][n] = 1;
g.edge[n][m] = 1;
}
}
// 打印图
void PrintGraph(Graph &g)
{
cout << "===========================================================" << endl;
// 水平表头
cout << "\t";
for(int i = 0; i < g.vertexNum;++i)
{
cout << g.vertex[i] << "\t";
}
for(int i =0 ; i < g.vertexNum;++i )
{
cout << "\n";
cout << g.vertex[i] << "\t";
for(int j = 0;j < g.vertexNum;++j)
{
cout << g.edge[i][j] << "\t";
}
}
cout << endl;
}
void test01()
{
Graph graph;
CreateGraph(graph);
PrintGraph(graph);
}
int main()
{
test01();
}
3.用邻接表存储的方式表示无向图的结构
3.1 邻接表
邻接矩阵不错的一种图存储结构,但是,对于边数相对于顶点较少的图,这种数据结构存在对存储空
间的极大浪费,因此我们找到一种数据与链表相结合的存储方法,称为邻接表。
邻接表的存储方式是这样的:
(1)图中顶点用一个一位数组存储,当然,顶点也可以用单链表老存储,不过,数组可以交通已的读取
顶点的信息,更加方便;
(2)图中每个顶点vi的所有邻接点构成了一个线性表,由于邻接点的个数不定,所以,用单链表存储,
无向图称为顶点vi的边表,有向图则称为顶点vi作为弧尾的出边表。
3.2 以邻接表方式存储无向图的设计
3.3 无向图以邻接表存储方式构建的代码
#include <iostream>
#include <stack>
#include <queue>
#include <cstring>
using namespace std;
#define MaxVertex 100
// 邻接点的结构体
struct edgeNode
{
// 当前顶点在顶点数组中的位置
int postion;
// 指向后继节点的指针
struct edgeNode* next;
// 节点相关的信息-info
int weight;
};
// 顶点的结构体
struct Vertex
{
// 顶点的名字
char name[9];
// 指向邻接点结构体的指针
struct edgeNode* first;
};
// 图结构-以邻接表来构建
struct Graph{
// 顶点数组
Vertex HeaderArray[MaxVertex];
// 顶点的个数
int vertexNum;
// 边的条数
int edgeNum;
};
// 求用户输入的顶点在顶点数组中的位置
int LocalVertex(Graph &g,char* name)
{
// 遍历顶点数组
for(int i = 0; i < g.vertexNum ; ++i)
{
if(strcmp(name,g.HeaderArray[i].name) == 0)
{
// 找到了,返回元素的下标
return i;
}
}
// 没找到
return -1;
}
// 构建一个图
void CreateGraph(Graph &g)
{
cout << "请输入图的顶点个数和边的个数: 顶点,边" << endl;
cin >> g.vertexNum >> g.edgeNum;
cout << "请输入" << g.vertexNum <<"个顶点的名字" << endl;
int i = 0;
for(i = 0; i < g.vertexNum; ++i)
{
cin >> g.HeaderArray[i].name;
g.HeaderArray[i].first = NULL; // 目前没有邻接点
}
cout << "请输入" << g.edgeNum << "条边的情况,顶点1,顶点2" << endl;
char v1[9],v2[9];
for(int i = 0; i < g.edgeNum; ++i)
{
cin >> v1 >> v2;
// 以M为头结点的链表,N是M的邻接点
// 求用户输入的顶点在顶点数组中的位置
int m = LocalVertex(g,v1); // 获取v1在二维数组中的位置
int n = LocalVertex(g,v2); // 获取v2在二维数组中的位置
// 链表中添加邻接点,这里采用了头插法,尾插法需要遍历到链表的尾部,会比较麻烦,所以这里用了头插法
edgeNode* pNew = new edgeNode;
// init pNew
pNew->postion = n; // 当前的节点在顶点数组中的位置
pNew->next = g.HeaderArray[m].first; // 将pNew设置为结点数组HeaderArray的第m个元素
g.HeaderArray[m].first = pNew;
#if 1
// 以N为头结点的链表,M是N的邻接点
edgeNode* pNew1 = new edgeNode;
pNew1->postion = m;
pNew1->next = g.HeaderArray[n].first;
g.HeaderArray[n].first = pNew1;
#endif
}
}
// 打印图
void PrintGraph(Graph &g)
{
cout << "===========================================================" << endl;
for(int i = 0; i < g.vertexNum;++i)
{
edgeNode* pNode = g.HeaderArray[i].first;
cout << g.HeaderArray[i].name<<":";
while(pNode != NULL)
{
int index = pNode->postion;
cout << g.HeaderArray[index].name << "\t";
pNode = pNode->next;
}
cout << endl;
}
cout << endl;
}
void test01()
{
Graph graph;
CreateGraph(graph);
PrintGraph(graph);
}
int main()
{
test01();
}