【数据结构】 图的邻接表

邻接表是图的另一种存储结构(使用链表的思想)。

该方式的基本思路:顶点表后指向邻接表,邻接表中依次为当前顶点的邻接点

准备工作

与邻接矩阵类似,在构造邻接表之前,需要存储各个顶点的信息,在这里使用结构体存储。因此,在构造邻接表之前,需要先定义两个结构体:邻接表结构体、顶点结构体。【其中,都需要用到指向邻接表的指针!】

struct EdgeNode{		//邻接表 
	int ad;				//记录邻接点的位置 
	EdgeNode *next;		//指向邻接表的指针
};
struct VertxNode{		//顶点表 
	char vertx;
	EdgeNode *firstEdge;//指向邻接表的指针
};

类的声明

与邻接矩阵类似,在这里,继续使用C++面向对象的方法完成构建。

class AlGraph{
public:
	AlGraph(char a[],int n,int e);	//通过顶点数据、点数、边数建邻接表 
	~AlGraph();						//使用链表存储,非静态存储,需析构!
	void dfs(int v);				
	void bfs(int v);				
private:
	VertxNode adjlist[MaxSize];			//结构数组存放各顶点 
	int vertxNum,edgeNum;				//点数、边数 
	
}; 

建表

构造函数

构造函数与单链表的头插法类似,但又不完全相同。如图,单链表中的first结点为一个结构体变量,其中包含next指针。

在实现单链表的头插法时,首先将插入元素的next指针与first指针指向同一位置,之后将头指针的next指针指向新插入的元素。而在邻接表构建中,顶点结构体就相当于单链表头插构造中的整个first结点,顶点结构体中的firstEdge指针就相当于单链表first结点的next指针!(如图所示)

【数据结构】 图的邻接表_第1张图片

邻接表的构造过程用以下代码实现:

AlGraph::AlGraph(char a[],int n,int e){
	vertxNum=n,edgeNum=e;
	int i,j,k;
	//顶点结构初始化(抄入顶点数据并将头指全部置空) 
	for(i=0;i>i>>j;			//输入顶点,i已存入顶点结构,j存入邻接点域。
		s=new EdgeNode;s->ad=j;			
		//将j挂链到i上 (头插)
		s->next=adjlist[i].firstEdge;
		adjlist[i].firstEdge=s;
	} 
} 

析构函数

由于邻接表使用链表存储数据,为动态存储,不同于邻接矩阵的数组存储结构。因此,需要手动写析构函数!

析构过程的思路及代码如下:

AlGraph::~AlGraph(){
	//使用链表存储邻接点,存储结构非静态,需循环删除指针
	EdgeNode *p,*q;		//工作指针p ,临时指针q(暂存被删除元素) 
	p=NULL,q=NULL;
	for(int i=0;inext;
			delete q;	//删除临时指针指向的数据 
			q=p; 		//更新临时指针指向 
		}
	}
} 

图的遍历

与邻接矩阵相同,有两种方式对图进行遍历:DFS、BFS。其思路与邻接矩阵时实现的思路完全一样,所不同的仅仅是对链表的遍历过程。

DFS

void AlGraph::dfs(int v){
	cout<ad;
		if(!vis[i]) dfs(i);	
		p=p->next;
	} 
}

BFS

void AlGraph::bfs(int v){
	//思路:用队列,将元素访问、标记、入队 
	int front,rear;
	front=rear=-1;
	int Q[MaxSize],j,t;		//t存储出队元素,j存储邻接点位置 
	cout<ad;
		if(!vis[j]){
			cout<next;
		}	
	} 
}

完整代码

​ 如图,测试边为:(0 1)(0 3)(0 4)(1 2)(2 4)(3 2)(3 4)

【数据结构】 图的邻接表_第2张图片

#include
using namespace std;
const int MaxSize=10;
int vis[MaxSize]={0};
struct EdgeNode{		//邻接表 
	int ad;				//记录邻接点位置 
	EdgeNode *next;
};
struct VertxNode{		//顶点表 
	char vertx;
	EdgeNode *firstEdge;//顶点表指向邻接表,指针为邻接表类型 
};
//思路:顶点表后指向邻接表,邻接表中依次为当前顶点的邻接点 
class AlGraph{
public:
	AlGraph(char a[],int n,int e);	//通过顶点数据、点数、边数建邻接表 
	~AlGraph();						//使用链表存储,非静态存储,需析构!
	void dfs(int v);				
	void bfs(int v);				
private:
	VertxNode adjlist[MaxSize];			//结构数组存放各顶点 
	int vertxNum,edgeNum;				//点数、边数 
	
}; 
AlGraph::AlGraph(char a[],int n,int e){
	vertxNum=n,edgeNum=e;
	int i,j,k;
	//顶点结构初始化(抄入顶点数据并将头指全部置空) 
	for(i=0;i>i>>j;			//输入顶点,i已存入顶点结构,j存入邻接点域。
		s=new EdgeNode;s->ad=j;			
		//将j挂链到i上 (头插)
		s->next=adjlist[i].firstEdge;
		adjlist[i].firstEdge=s;
	} 
} 

void AlGraph::dfs(int v){
	cout<ad;
		if(!vis[i]) dfs(i);	
		p=p->next;
	} 
}
			
void AlGraph::bfs(int v){
	//思路:用队列,将元素访问、标记、入队 
	int front,rear;
	front=rear=-1;
	int Q[MaxSize],j,t;		//t存储出队元素,j存储邻接点位置 
	cout<ad;
		if(!vis[j]){
			cout<next;
		}	
	} 
}

AlGraph::~AlGraph(){
	//使用链表存储邻接点,存储结构非静态,需循环删除指针
	EdgeNode *p,*q;		//工作指针p ,临时指针q(暂存被删除元素) 
	p=NULL,q=NULL;
	for(int i=0;inext;
			delete q;	//删除临时指针指向的数据 
			q=p; 		//更新临时指针指向 
		}
	}
} 

int main( )
{

	char ch[ ] = {'A','B','C','D','E'};
	int i;
	AlGraph ALG(ch, 5, 7);               //建立具有5个顶点6条边的有向图
	
	for (i = 0; i < MaxSize; i++)
		vis[i] = 0;
	cout << "深度优先遍历序列是:";
	ALG.dfs(0);                       //从顶点0出发进行深度优先遍历
	cout<

你可能感兴趣的:(C++,数据结构,链表,算法)