图的邻接表表示

有一幅图:


图的“顶点”为:1,2,3,4,5,6,7,8 


用下面三个结构体表示图的邻接表存储信息:

//“结点”结构体,存储与“顶点”相连的顶点
typedef struct node
{
	int adjVex; //“顶点”对应的“结点”信息
	struct node *next; //指向下一个与“某顶点”相连的结点
}EdgeNode;


//顶点结构体
typedef struct vnode
{
	char vertex; //顶点信息
	EdgeNode *firstEdge; //指向第一个与“此顶点”相连的结点
}AdjList;


//图结构体
typedef struct
{
	AdjList vertexs[VERTEXNUM]; //邻接表,即顶点数组
	int verNum, edgeNum; //图中当前的顶点和边数
}Graph;

顶点1对应的顶点(结点)为2,3,所以“顶点1的表”构造步骤:
1->NULL //1初始指向的结点位置NULL 
1->2->NULL //2指向1指向的结点位置NULL,1指向2
1->3->2->NULL  //3指向1指向的结点位置2,1指向3
剩余顶点表构造步骤相同:
2->5->4->1->NULL
3->7->6->1->NULL
4->8->2->NULL
5->8->2->NULL
6->7->3->NULL 
7->6->3->NULL
8->5->4->NULL

注意:边的输入顺序会影响邻接表存储顺序(1->3->2->NULL也可以是1->2->3->NULL),进而影响遍历结果输出。


下面代码实现为图的邻接表构造与搜索:

#include <cstdio>
#include <cstdlib>
#include <queue>
using namespace std;

#define VERTEXNUM 8 //顶点个数
#define DONE 1  //visitedV
#define UNDONE 0  
bool visitedV[VERTEXNUM];

//结点结构体
typedef struct node
{
	int adjVex; //顶点对应的结点信息
	struct node *next; //指向下一条边的指针
}EdgeNode;

//顶点结构体
typedef struct vnode
{
	char vertex; //顶点信息
	EdgeNode *firstEdge; //指向第一条依附该顶点的边的指针
}AdjList;

//图结构体
typedef struct
{
	AdjList vertexs[VERTEXNUM]; //邻接表
	int verNum, edgeNum; //图中当前的顶点和边数
}Graph;

void MakeGraph(Graph *graph)
{

	int i, j;
	printf("请输入图的顶点数n和边数e:\n");
	//scanf("%d%d", &graph->verNum, &graph->edgeNum);
	graph->verNum = 8;
	graph->edgeNum = 18;
	printf("请输入顶点信息(顶点号<CR>)每个顶点以回车作为结束:\n");
    /*
	for(i = 0; i < graph->verNum; i++)
	{
		getchar();
		scanf("%c", &graph->vertexs[i].vertex);
		graph->vertexs[i].firstEdge = NULL; //初始第一条边为空
	}
	*/
	//char my_vertexs[8] = {'a','b','c','d','e','f','g','h'};
    char my_vertexs[8] = {'1','2','3','4','5','6','7','8'};

    for(int x = 0; x<8; x++)
	{
	  graph->vertexs[x].vertex = my_vertexs[x];
	  graph->vertexs[x].firstEdge = NULL;
    }	
	printf("请输入每条边对应的两个顶点的序号(格式为i,j):\n");
	//1,2  1,3  2,1  2,4  2,5  3,1  3,6  3,7  4,2
	//4,8  5,2  5,8  6,3  6,7  7,3  7,6  8,4  8,5
	int a[18] = {1,1,2,2,2,3,3,3,4,4,5,5,6,6,7,7,8,8};
	int b[18] = {2,3,1,4,5,1,6,7,2,8,2,8,3,7,3,6,4,5};
	EdgeNode *p;
	for(int k = 0; k < graph->edgeNum; k++)
	{
		//scanf("%d,%d", &i, &j);  //读入边<vi,vj>的序号
		i = a[k];
		j = b[k];
		p = (node *)malloc(sizeof(node)); //生成新的结点
		p->adjVex = j - 1; //顶点对应的结点信息(也是顶点);因为用的是数组,数组下标减1
		//结点指向顶点指向的位置;(最初顶点指向NULL,所以第1个结点就指向空;下一行代码中,顶点指向第1个结点;
		//来了第2个结点,第2个结点便指向第1个结点,而后下一行代码中,顶点指向第2个结点)
		p->next = graph->vertexs[i - 1].firstEdge;
		graph->vertexs[i - 1].firstEdge = p;//顶点指向结点;
	}
}

void DFSTraverse(Graph *graph, int v)
{
	visitedV[v] = DONE;
	printf("深度遍历:结点%c\n", graph->vertexs[v].vertex);
	EdgeNode *p = graph->vertexs[v].firstEdge;
	while(p != NULL)
	{
		if(!visitedV[p->adjVex])
			DFSTraverse(graph, p->adjVex);
		p = p->next;
	}
}

void DFS(Graph *graph)
{
	int i;
	for(i = 0; i < graph->verNum; i++)
		visitedV[i] = UNDONE;

	for(i = 0; i < graph->verNum; i++)
		if(!visitedV[i])
			DFSTraverse(graph, i);
}

void BFS(Graph *graph)
{
	int i, j, k;
	queue<int> q;
	EdgeNode *p;
	for(i = 0; i < graph->verNum; i++) //初始化访问标识数组
		visitedV[i] = UNDONE;

	for(i = 0; i < graph->verNum; i++)
	{
		if(!visitedV[i])
		{
			visitedV[i] = DONE;
			printf("广度优先遍历:结点%c\n", graph->vertexs[i].vertex);
			q.push(i); //入栈
			while(!q.empty())
			{
				j = q.front(); 
				q.pop();  //出栈
				p = graph->vertexs[j].firstEdge;
				while(p)
				{
					if(!visitedV[p->adjVex])
					{
						printf("广度优先遍历:结点%c\n", graph->vertexs[p->adjVex].vertex);
						visitedV[p->adjVex] = DONE;
						q.push(p->adjVex);
					}
					p = p->next;
				}
			}
		}
	}
}

int main()
{
	Graph *graph = (Graph *)malloc(sizeof(Graph));
	MakeGraph(graph); //建立图的邻接表
	//DFS(graph); //深度优先遍历
	BFS(graph); //广度优先遍历

	return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值