图的邻接表创建以及遍历

对于图的邻接表存储以及遍历,搞清思路是十分必要的。

1、首先搞清结构体。不同的处理问题的思路,对应着不同的结构体封装。下面 以我的处理方式为例为大家展示:

#define max_vertex_num 100 //该图可以为维护最大的结点个数。

typedef struct Arcnode
{
	int    adjvex;//该弧所指向的顶点的位置
	struct Arcnode  *nextarc;
	char   *info;
}Arcnode;

typedef struct Vnode
{
	char data;
	Arcnode *firstrac;//对于每一个邻接链表,这相当于是链表的头指针。
}Vnode,Adjlist[max_vertex_num];

typedef struct
{
	Adjlist vertices;
	int vexnum,arcnum;
	int kind;//1为有向图,0为无向图。
}Algrap;

看过我封装的结构体,相信大家已经很清楚的了解到,图、结点、弧之间存在一定的联系。也清楚了结构体中所具有的属性。 2、先引入几个函数以及实现。 int creatgrap(Algrap *map1); 创建图。对于每个节点的临接点所形成的链表采用头插法初始化,链表中储存的数据保存节点位置。

void  DFSTraverse(Algrap *G); 保证每个节点都会被遍历到,尽管该图不是连通图。遍历的顺序默认为从最大连通图中下表最小的开始。

void DFS(Algrap *G,int i); 图的递归遍历。

void printf(Algrap G);

把图的逻辑存储关系打印出来。

下面给出函数的实现:

//图的创建。
int creatgrap(Algrap *map1)
{
	int i,j;
	cout<<"请输入图的结点数以及弧的条数:";
	cin>>map1->vexnum>>map1->arcnum;
	cout<<"      请选择图的类型:        "<<endl;
	cout<<"      1  有向图               "<<endl;
	cout<<"      2  无向图               "<<endl;
	cout<<"      请输入选择的数字:      "<<endl;
	cin>>map1->kind;

	while(map1->kind!=1&&map1->kind!=2)
	{
	    cout<<"请重新输入选择数字,你输入的数字不合法!"<<endl;
		cin>>map1->kind;
	}

	for(i=0;i<map1->vexnum;i++)
	{
		cout<<"请输入节点数据:";
		cin>>map1->vertices[i].data;
		map1->vertices[i].firstrac=NULL;
	}


	for(i=0;i<map1->arcnum;i++)
	{
		char a,b;
		int temp1=0,temp2=0;
		cout<<"请输入两个有关系的节点:";  
		cin>>a>>b;

		for(j=0;j<map1->vexnum;j++)
		{
			if(map1->vertices[j].data==a)
				temp1=j;
			if(map1->vertices[j].data==b)
				temp2=j;
		}

		Arcnode *p,*q;

		p=(Arcnode*)malloc(sizeof(Arcnode));
		p->adjvex=temp2;
		p->nextarc=map1->vertices[temp1].firstrac;//插入表头.采用头插法,先进的弧、遍历后出。后进的弧、遍历先出。
		map1->vertices[temp1].firstrac=p;
		if(map1->kind==2)
		{
			q=(Arcnode*)malloc(sizeof(Arcnode));
			q->adjvex=temp1;
			q->nextarc=map1->vertices[temp2].firstrac;
			map1->vertices[temp2].firstrac=q;
		}
	}
	return 0;
}

void  DFSTraverse(Algrap *G)//保证每个节点都会被遍历到,尽管该图不是连通图。遍历的顺序默认为从最大连通图中下标最小的开始。
{
   int i;
   for(i=0;i<G->vexnum;i++)
			visited[i]=false;
   for(i=0;i<G->vexnum;i++)
	   if(!visited[i])
		   DFS(G,i);
}

void DFS(Algrap *G,int i)
{
	Arcnode *p=NULL;
	printf("访问顶点;%c\n",G->vertices[i].data);
	visited[i]=true;
	p=G->vertices[i].firstrac;
	while(p)
	{
		if(!visited[p->adjvex])
			DFS(G,p->adjvex);
		p=p->nextarc;
	}
}

void printf(Algrap G)
{
    int i;
	Arcnode *p;
	cout<<"下面把图的逻辑存储打印出来:"<<endl;
	for(i=0;i<G.vexnum;i++)
	{
		cout<<G.vertices[i].data;
		p=G.vertices[i].firstrac;
		while(p)
		{
			cout<<"->"<<p->adjvex;
			p=p->nextarc;
		}
		cout<<endl;
	}
}

下面给出完整的程序:

// 邻接表图的建立与遍历.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include<cstdlib>
#include<cstdio>
#include<iostream>
using namespace std;

bool visited[100];

#define max_vertex_num 100 //该图可以为维护最大的结点个数。

typedef struct Arcnode
{
	int    adjvex;//该弧所指向的顶点的位置
	struct Arcnode  *nextarc;
	char   *info;
}Arcnode;

typedef struct Vnode
{
	char data;
	Arcnode *firstrac;//对于每一个邻接链表,这相当于是链表的头指针。
}Vnode,Adjlist[max_vertex_num];

typedef struct
{
	Adjlist vertices;
	int vexnum,arcnum;
	int kind;//1为有向图,2为无向图。
}Algrap;

int creatgrap(Algrap *map1);
void  DFSTraverse(Algrap *G);
void DFS(Algrap *G,int i);
void printf(Algrap G);

int main()
{
	Algrap *map=(Algrap* )malloc(sizeof(Algrap));
	creatgrap(map);
	printf(*map);
	DFSTraverse(map);
	return 0;
}


//图的创建。
int creatgrap(Algrap *map1)
{
	int i,j;
	cout<<"请输入图的结点数以及弧的条数:";
	cin>>map1->vexnum>>map1->arcnum;
	cout<<"      请选择图的类型:        "<<endl;
	cout<<"      1  有向图               "<<endl;
	cout<<"      2  无向图               "<<endl;
	cout<<"      请输入选择的数字:      "<<endl;
	cin>>map1->kind;

	while(map1->kind!=1&&map1->kind!=2)
	{
	    cout<<"请重新输入选择数字,你输入的数字不合法!"<<endl;
		cin>>map1->kind;
	}

	for(i=0;i<map1->vexnum;i++)
	{
		cout<<"请输入节点数据:";
		cin>>map1->vertices[i].data;
		map1->vertices[i].firstrac=NULL;
	}


	for(i=0;i<map1->arcnum;i++)
	{
		char a,b;
		int temp1=0,temp2=0;
		cout<<"请输入两个有关系的节点:";  
		cin>>a>>b;

		for(j=0;j<map1->vexnum;j++)
		{
			if(map1->vertices[j].data==a)
				temp1=j;
			if(map1->vertices[j].data==b)
				temp2=j;
		}

		Arcnode *p,*q;

		p=(Arcnode*)malloc(sizeof(Arcnode));
		p->adjvex=temp2;
		p->nextarc=map1->vertices[temp1].firstrac;//插入表头.采用头插法,先进的弧、遍历后出。后进的弧、遍历先出。
		map1->vertices[temp1].firstrac=p;
		if(map1->kind==2)
		{
			q=(Arcnode*)malloc(sizeof(Arcnode));
			q->adjvex=temp1;
			q->nextarc=map1->vertices[temp2].firstrac;
			map1->vertices[temp2].firstrac=q;
		}
	}
	return 0;
}

void  DFSTraverse(Algrap *G)//保证每个节点都会被遍历到,尽管该图不是连通图。遍历的顺序默认为从最大连通图中下表最小的开始。
{
   int i;
   for(i=0;i<G->vexnum;i++)
			visited[i]=false;
   for(i=0;i<G->vexnum;i++)
	   if(!visited[i])
		   DFS(G,i);
}

void DFS(Algrap *G,int i)
{
	Arcnode *p=NULL;
	printf("访问顶点;%c\n",G->vertices[i].data);
	visited[i]=true;
	p=G->vertices[i].firstrac;
	while(p)
	{
		if(!visited[p->adjvex])
			DFS(G,p->adjvex);
		p=p->nextarc;
	}
}

void printf(Algrap G)
{
    int i;
	Arcnode *p;
	cout<<"下面把图的逻辑存储打印出来:"<<endl;
	for(i=0;i<G.vexnum;i++)
	{
		cout<<G.vertices[i].data;
		p=G.vertices[i].firstrac;
		while(p)
		{
			cout<<"->"<<p->adjvex;
			p=p->nextarc;
		}
		cout<<endl;
	}
}

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/cc_lch_dp/article/details/17095973
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞