图(Graph)-图的存储

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();
}

猜你喜欢

转载自blog.csdn.net/Edidaughter/article/details/120937035