目录
存储形式
顶点的结构
typedef struct VNode
{
VerTexType data; //顶点信息
ArcNode* firstarc; //指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNum]; //AdjList表示邻接表类型
此处AdjList v相当于VNode v[MVNum]
弧(边)的结点结构
#define MVNum 100 //最大顶点数
typedef struct ArcNode //边结点
{
int adjvex; //该边所指向的顶点的位置
struct ArcNode* nextarc; //指向下一条边的指针
Otherinfo info; //和边相关的信息
}ArcNode;
图的结构定义
typedef struct
{
AdjList vertices;//vertices--vertex的复数
int vexnum, arcnum; //图的当前顶点数和弧数
}ALGraph;
邻接表操作举例说明
采用邻接表法创建无向网
Status CreateUDG(ALGraph& G)//采用邻接表表示法,创建无向图G
{
int v1, v2,i,j;
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
for (int i = 0; i < G.vexnum; ++i) //输入各点,构造表头结点表
{
cin >> G.vertices[i].data; //输入顶点值
G.vertices[i].firstarc = NULL; //初始化表头结点的指针域
}
for (int k = 0; k < G.arcnum; ++k)//输入各边,构造邻接表
{
cin >> v1 >> v2; //输入一条边依附的两个顶点
i = LocateVex(G, v1);
j = LocateVex(G, v2);
p1 = new ArcNode; //生成一个新的结点*p1
p1->adjvex = k; //邻接点序号为j
p1->nextarc = G.vertices[i].firstarc;
G.vertices[i].firstarc = p1;//将新结点*p1插入顶点vi的边表头部
p2 = new ArcNode; //生成另一个对称的新的边结点*p2
p2->adjvex = i; //邻接点序号为i
p2->nextarc = G.vertices[j].firstarc;
G.vertices[j].firstarc = p2; //将新结点*p2插入顶点vj的边表头部
}
return OK;
}
建立有向网时候后面四行可以省略,只建立出度的即可;只留下面四行,省略上面四行,只建立入度边,可以建立逆邻接矩阵
邻接表的特点
邻接矩阵与邻接表表示法的关系
完整代码
#include <iostream>
using namespace std;
//边表结点机构,一个adjvex用来存储邻接点的位置,一个next指针用来指向下一个结点
typedef struct EdgeNode
{
int adjvex;
struct EdgeNode* next;
}EdgeNode;
//顶点表结点结构,data来存储数据,一个firstedge是用来指向边表的第一个结点
typedef struct
{
string data;
EdgeNode* firstedge;
}AdjList;
//里面的adjList[15]表示给顶点表开了15的单位大小,然后numVertex,numEdge是一个图的顶点数和边数
typedef struct
{
AdjList adjList[15];
int numVertex, numEdge;
}GraphAdjList;
//遍历图的顶点,返回该顶点的下标
int local(GraphAdjList G, string val)
{
for (int i = 0; i < G.numVertex; i++)
{
if (G.adjList[i].data == val)
return i;
}
return -1;
}
//创建邻接表
void CreateGraph(GraphAdjList& G)
{
int i, j, k;
string v1, v2;
EdgeNode* e, * p, * q;
cout << "请输入顶点数和边数,并以空格隔开:" << endl;
cin >> G.numVertex >> G.numEdge;
cout << "请输入顶点的信息:" << endl;
for (i = 0; i < G.numVertex; i++)
{
cout << "第" << i + 1 << "个顶点:" << endl;
cin >> G.adjList[i].data;
G.adjList->firstedge = NULL;
}
for (k = 0; k < G.numEdge; k++)
{
cout << "请输入(vi,vj)上的顶点信息:" << endl;
cin >> v1 >> v2;
i = local(G,v1);
j = local(G,v2);
if (G.adjList[i].firstedge == NULL)
{
e = new EdgeNode;
e->adjvex = j;
e->next = NULL;
G.adjList[i].firstedge = e;
}
else
{
p = G.adjList[i].firstedge;
while (p->next != NULL)
{
p = p->next;
}
e = new EdgeNode;
e->adjvex = j;
e->next = NULL;
p->next = e;
}
if (G.adjList[j].firstedge == NULL)
{
e = new EdgeNode;
e->adjvex = i;
e->next = NULL;
G.adjList[j].firstedge = e;
}
else
{
p = G.adjList[j].firstedge;
while (p->next != NULL)
{
p = p->next;
}
e = new EdgeNode;
e->adjvex = i;
e->next = NULL;
p->next = e;
}
}
}
//打印邻接表
void Prin(GraphAdjList G)
{
cout << "所建立的邻接表如下所示:" << endl;
for (int i = 0; i < G.numVertex; i++)
{
cout << G.adjList[i].data;//先输出顶点信息
EdgeNode* e = G.adjList[i].firstedge;
while (e)
{
cout << "-->" << e->adjvex;
e = e->next;
}
cout << endl;
}
}
//状态数组
bool DFSvisited[50];//用于深度的标记数组
bool BFSvisited[50];//用于广搜的标记数组
//深度优先搜索
void DFS(GraphAdjList G, int i)
{
EdgeNode* p;
DFSvisited[i] = true;
cout << G.adjList[i].data << " ";
p = G.adjList[i].firstedge;
while (p)
{
if (!DFSvisited[p->adjvex])
DFS(G.p->adjvex);
p = p->next;
}
}
void DFSTraverse(GraphAdjList G)
{
for (int i = 0; i < G.numVertex; i++)
DFSvisited[i] = false;
for (int i = 0; i < G.numVertex; i++)
{
if (!DFSvisited[i])
DFS(G, i);
}
}
//广度优先搜索
//把相应STL中queue的操作替换掉就可以了
void BFSTraverse(GraphAdjList G)
{
EdgeNdoe* p;
queue<int>q;
for (int i = 0; i < G.numVertex; i++)
BFSvisited[i] = false;
for (int i = 0; i < G.numVertex; i++)
{
if (!BFSvisited[i])
{
BFSvisited[i] = true;
cout<<G.adjList[i].data << " ";
q.push(i);
while (!q.empty())
{
int count = q.front();
q.pop();
p = G.adjList[count].firstedge;
while (p)
{
if (!BFSvisited[p->adjvex])
{
BFSvisited[p->adjvex] = true;
cout << G.adjList[p->adjvex].data << " ";
q.push(p->adjvex);
}
p = p->next;
}
}
}
}
}