1.邻接表
邻接表是一种链式存储结构。它用n个带头结点的单链表代替邻接矩阵的n行,并对图中的每个顶点v建立一个带头结点的单链表,将顶点v的相关信息存放在表头,表中的其余顶点用来存放与顶点v相关边的信息,例如其邻接点的编号、相应的边的权值。下图是相关图的邻接表形式。
2.图的邻接表存储结构声明
#define MAX_V 20
#define OK 1
#define ERROR 0
typedef int ElemType, Status;
typedef int GraphKind; //定义图的类型,无向图0, 有向图1,无向网2,有向网3
//定义边的结点结构类型
typedef struct ArcNode {
int adjvex; //该边的终边编号
int weight; //该边的权值
struct ArcNode* nextarc;
};
//定义顶点的结构类型
typedef struct VexNode{
ElemType data; //顶点的值
ArcNode* firstarc; //指向第一条与该顶点有关的指针
};
//定义邻接表表示的图
class ALGraph {
private:
VexNode vexnode[MAX_V]; //定义邻接表
int vexnum, arcnum;
GraphKind type; //定义图的类型,无向图0, 有向图1,无向网2,有向网3
public:
Status CreateGraph(); //图的创建
Status DestroyGraph(); //图的销毁
ElemType GetVex(int v); //返回编号v顶点的值
Status InsertVex(); //插入顶点
Status InsertArc(int v, int w); //插入边
Status DeleteVex(int v); //删除顶点
Status DeleteArc(int v, int w); //删除边
Status Print(); //打印邻接表
};
3.基于邻接表的无向图的创建
//基于邻接表的无向图创建
Status ALGraph::CreateGraph() {
cin >> vexnum >> arcnum; //输入图的顶点数和边数
int i, v, w;
for (i = 0; i < vexnum; i++) { //输入各顶点的信息
cin >> vexnode[i].data;
vexnode[i].firstarc = NULL;
}
ArcNode* p;
for (i = 0; i < arcnum; i++) { //创建各边
cin >> v >> w; //输入一条边的两个顶点
p = new ArcNode; //创建一个用于存放当前边的顶点
if (p == NULL) exit(0);
p->adjvex = w; //该边的起点是v终点是w
p->nextarc = vexnode[v].firstarc; //将该边结点链接到v号顶点
vexnode[v].firstarc = p;
p = new ArcNode; //由于是无向图还要创建一条对称的边,起点w终点v
if (p == NULL) exit(0);
p->adjvex = v;
p->nextarc = vexnode[w].firstarc; //将该边链接到w号顶点
vexnode[w].firstarc = p;
}
return OK;
}
4.基于邻接表的无向图插入顶点、插入边
//插入顶点
Status ALGraph::InsertVex() {
int v, w;
ArcNode* p;
vexnum++;
cin >> vexnode[vexnum - 1].data;
vexnode[vexnum - 1].firstarc = NULL;
while (true) {
cin >> v >> w;
if (v == -1)
break;
p = new ArcNode;
if (p == NULL) exit(0);
p->adjvex = w; //该边的起点是v终点是w
p->nextarc = vexnode[v].firstarc; //将该边结点链接到v号顶点
vexnode[v].firstarc = p;
p = new ArcNode; //由于是无向图还要创建一条对称的边,起点w终点v
if (p == NULL) exit(0);
p->adjvex = v;
p->nextarc = vexnode[w].firstarc; //将该边链接到w号顶点
vexnode[w].firstarc = p;
arcnum++;
}
return OK;
}
//插入边
Status ALGraph::InsertArc(int v, int w) {
ArcNode* p;
p = new ArcNode;
if (p == NULL) exit(0);
p->adjvex = w; //该边的起点是v终点是w
p->nextarc = vexnode[v].firstarc; //将该边结点链接到v号顶点
vexnode[v].firstarc = p;
p = new ArcNode; //由于是无向图还要创建一条对称的边,起点w终点v
if (p == NULL) exit(0);
p->adjvex = v;
p->nextarc = vexnode[w].firstarc; //将该边链接到w号顶点
vexnode[w].firstarc = p;
arcnum++;
return OK;
}
5.基于邻接表的无向图删除顶点、删除边
//删除顶点
Status ALGraph::DeleteVex(int v) {
ArcNode* p, * q;
int i;
p = q = vexnode[v].firstarc;
while (p) {
i = p->adjvex;
ArcNode* p1, * q1;
p1 = q1 = vexnode[i].firstarc;
if (p1->adjvex == v) {
vexnode[i].firstarc = p1->nextarc;
delete p1;
p1 = q1 = NULL;
}
else {
while (true) {
p1 = p1->nextarc;
if (p1->adjvex == v) {
q1->nextarc = p1->nextarc;
delete p1;
p1 = NULL;
break;
}
q1 = p1;
}
}
p = p->nextarc;
delete q;
q = p;
arcnum--;
}
vexnode[v].firstarc = NULL;
for (i = v; i < vexnum - 1; i++)
vexnode[i] = vexnode[i + 1];
vexnum--;
return OK;
}
//删除边
Status ALGraph::DeleteArc(int v, int w) {
ArcNode* p, *q;
p = q = vexnode[v].firstarc;
if (p->adjvex == w) {
vexnode[v].firstarc = p->nextarc;
delete p;
p = q = NULL;
}
else {
while (true) {
p = p->nextarc;
if (p->adjvex == w) {
q->nextarc = p->nextarc;
delete p;
p = q = NULL;
break;
}
}
}
p = q = vexnode[w].firstarc;
if (p->adjvex == v) {
vexnode[w].firstarc = p->nextarc;
delete p;
p = q = NULL;
}
else {
while (true) {
p = p->nextarc;
if (p->adjvex == v) {
q->nextarc = p->nextarc;
delete p;
p = q = NULL;
break;
}
}
}
arcnum--;
return OK;
}
6.邻接表的打印
//打印邻接表
Status ALGraph::Print() {
int i;
ArcNode* p;
for (i = 0; i < vexnum; i++) {
p = vexnode[i].firstarc;
cout << vexnode[i].data << "-->";
while (p) {
cout << p->adjvex << " ";
p = p->nextarc;
}
cout << endl;
}
return OK;
}
7.main函数
#include<iostream>
using namespace std;
#include"ALGraph.h"
int main() {
ALGraph graph;
graph.CreateGraph();
graph.Print();
cout << endl;
cout << graph.GetVex(2)<< endl;
graph.InsertVex();
graph.Print();
cout << endl;
graph.InsertArc(0, 4);
graph.Print();
cout << endl;
return OK;
}