今天想练习一下图算法,有些图算法的基础数据结构是邻接表,于是想着用C实现一下,虽说wiki上有一个邻接表的实现,但是自己还是想练一下手,在网上也搜到了别人的邻接表实现,发现大同小
异,然后就在别人的基础上修改了一下得到了这个版本,记录一下,供以后练习使用。
1.邻接表概念
一张图,如果不考虑空间占用问题的话,用邻接矩阵存储是最方便的了,但有时候,图很稀疏,用矩阵存储就不划算了,这时候可以考虑用邻接表来实现,另外,有些算法用邻接表比较合适。
邻接表的图示如下(网络来源):
关于邻接表的概念,要清晰易懂的话上面的链接就很好,要详尽的话看wiki就好了,我的代码是在下面这个网页的基础上修改的。
2.邻接表需注意的点
- 一般需要一个顶点数组来保存顶点信息
- 每个顶点数组后面跟着一个单链表,表示与该顶点直接相连的顶点
- 顶点数组中保存有一个指向单链表头部的指针,以及顶点信息的相应描述
3.邻接表的实现
头文件:
/*
by areslipan@163.com
filename: adjlist.h
*/
#ifndef _ADJLIST_
#define _ADJLIST_
#include<iostream>
using namespace std;
#define MAXVEX 100 /* 最大顶点数,应由用户定义 */
typedef int VertexType; /* 顶点类型应由用户定义 */
typedef int EdgeType; /* 边上的权值类型应由用户定义 */
typedef struct EdgeNode/* 边表结点 */
{
int adjvex;/* 邻接点域,存储该顶点对应的下标 */
EdgeType weight;/* 用于存储权值,对于非网图可以不需要 */
struct EdgeNode *next; /* 链域,指向下一个邻接点 */
} EdgeNode;
typedef struct VextexNode/* 顶点表结点 */
{
VertexType data;/* 顶点域,存储顶点信息 */
EdgeNode *firstedge;/* 边表头指针 */
} VextexNode, AdjList[MAXVEX];
typedef struct
{
AdjList adjList;
int numNodes, numEdges; /* 图中当前顶点数和边数 */
} GraphAdjList;
void create_adjlist_graph(GraphAdjList *Gp);
void show_adjlist_graph(GraphAdjList *Gp);
void destroy_adjlist_graph(GraphAdjList *Gp);
#endif实现文件:
/*
by areslipan@163.com
filename : adjlist.cpp
*/
#include "adjlist.h"
void create_adjlist_graph(GraphAdjList *Gp)
{
int i, j, k,w;
EdgeNode *pe;
cout << "输入顶点数和边数(空格分隔):" << endl;
cin >> Gp->numNodes >> Gp->numEdges;
cout << "输入顶点信息:" << endl;
for (i = 0 ; i < Gp->numNodes; i++)
{
cin >> Gp->adjList[i].data;
Gp->adjList[i].firstedge = NULL;/* 将边表置为空表 */
}
for (k = 0; k < Gp->numEdges; k++)/* 建立边表 */
{
cout << "输入边(vi,vj,w)的顶点序号i,j(空格分隔):" << endl;
cin >> i >> j >> w;
pe = (EdgeNode *)malloc(sizeof(EdgeNode));
pe->adjvex = j;/* 邻接序号为j */
pe->weight = w;
/* 将pe的指针指向当前顶点上指向的结点 */
pe->next = Gp->adjList[i].firstedge;
Gp->adjList[i].firstedge = pe;/* 将当前顶点的指针指向pe */
//如果是无向图可以加上下面这段代码
/* pe = (EdgeNode *)malloc(sizeof(EdgeNode));
pe->adjvex = i;
pe->next = Gp->adjList[j].firstedge;
Gp->adjList[j].firstedge = pe;*/
}
cout<<"有向图的邻接表创建成功..."<<endl;
}
void show_adjlist_graph(GraphAdjList *Gp)
{
cout<<"邻接表如下:"<<endl;
if(Gp->numNodes == 0 || Gp->numEdges == 0)cout<<"The adjlist is empty!"<<endl;
for(int v=0;v<Gp->numNodes;++v)
{
cout<<"V"<<v<<":";
if(Gp->adjList[v].firstedge==NULL)cout<<"NULL"<<endl;
else
{
EdgeNode *cur=Gp->adjList[v].firstedge;
while(cur!=NULL)
{
cout<<"V"<<cur->adjvex<<"("<<cur->weight<<")"<<" ";
cur=cur->next;
}
cout<<endl;
}
}
}
void destroy_adjlist_graph(GraphAdjList *Gp)
{
if(Gp->numNodes == 0 || Gp->numEdges == 0)return ;
else
{
for(int v=0;v<Gp->numNodes;++v)
{
while(Gp->adjList[v].firstedge!=NULL)
{
EdgeNode *cur=Gp->adjList[v].firstedge;
Gp->adjList[v].firstedge=cur->next;
free(cur);
}
}
}
cout<<"邻接表销毁成功..."<<endl;
}
测试文件:
/*
by areslipan@163.com
filename : test.cpp
*/
#include "adjlist.h"
using namespace std;
int main()
{
GraphAdjList g;
create_adjlist_graph(&g);
show_adjlist_graph(&g);
destroy_adjlist_graph(&g);
show_adjlist_graph(&g);
system("pause");
}