图的存储
邻接矩阵
图是一种多对多的数据结构,对于一个有n个顶点的有向图采用n阶方阵来表示。M[i][j]
为真则存在边m->n,否则不存在边;或者,用M[i][j]
存储边的权值。
无向图的一条边可以当作一对有向边,或者采用三角矩阵存储无向图。
十字链表
图由顶点的集合和每个顶点的一组边来表示,可以使用数组存储所有顶点。可以用链表存储一个顶点的出边,顶点作为链表的头结点。同理,具有相同终点的一组边也可以组成一个链表,终点可以作为链表头结点。
这样,每个边节点都属于两个链表(同起点和同终点),可以形象的表示成一个十字状结构。
边定义:
typedef struct Edge {
int headvex; //起点索引
int tailvex; //终点索引
struct Edge *outlink; //出边链表的next指针
struct Edge *inlink; //入边链表的next指针
int val; //权值
} Edge;
顶点定义:
typedef struct {
int val;
Edge *firstin; //入边链表头节点
Edge *firstout; //出边链表头节点
} Vertex;
定义建立链表的函数
void getOList(Vertex *vertexs, int m) {
int i, j, k;
Edge *edge;
for (i = 0; i < m; i++) {
vertexs[i].firstin = NULL;
vertexs[i].firstout = NULL;
}
while (scanf("%d %d", &i, &j) != EOF) {
//append
edge = (Edge *)malloc(sizeof(Edge));
edge->headvex = i;
edge->tailvex = j;
appendOutEdge(&vertexs[i], edge); //添加到出边链表中
appendInEdge (&vertexs[j], edge); //添加到入边链表中
}
}
工具函数:
void appendInEdge(Vertex *vertex, Edge *edge) {
Edge *ptr;
edge->inlink = NULL;
if(vertex->firstin) {
ptr = vertex->firstin;
while(ptr->inlink) {
ptr = ptr->inlink;
}
ptr->inlink = edge;
}
else {
vertex->firstin = edge;
}
}
void appendOutEdge(Vertex *vertex, Edge *edge) {
Edge *ptr;
edge->outlink = NULL;
if(vertex->firstout) {
ptr = vertex->firstout;
while(ptr->outlink) {
ptr = ptr->outlink;
}
ptr->outlink = edge;
}
else {
vertex->firstout = edge;
}
}
访问指定顶点:
int getEdge(Vertex *vertexs, int x, int y) {
Edge *ptr;
ptr = vertexs[x].firstout;
while (ptr) {
if (ptr->tailvex == y) {
return ptr->val;
}
}
return -1;
}
图的遍历
图的遍历是指不重不漏的按照顶点之间的边访问所有顶点。图的的遍历与树的遍历类似,但是需要标记已访问过的顶点。
图的遍历只需要访问顶点和访问边的接口即可,与具体存储方式无关。为了效率起见这里还是提供了十字链表专用的遍历算法。
深度优先搜索
int visited[M];
void DFS(int **matrix, int m) {
int i;
for (i = 0; i < M; i++) {
visited[i] = 0;
}
for (i = 0; i < m; i++) {
if (!visited[i]) {
doDFS(matrix,m,i);
}
}
}
void doDFS(int **matrix, int m, int v) {
int i;
visited[v] = 1;
printf("%d\n",v + 1);
for (i = 0; i < m; i++) {
if (matrix[v][i]) {
if (!visited[i]) {
doDFS(matrix, m, i);
}
}
}
}
十字链表:
int visited[M];
void DFS(Vertex *vertexs, int m) {
int i;
for (i = 0; i < M; i++) {
visited[i] = 0;
}
for (i = 0; i < m; i++) {
if (!visited[i]) {
doDFS(vertexs,m,i);
}
}
}
void doDFS(Vertex *vertexs, int m, int v) {
int j;
Edge *ptr = vertexs[v].firstout;
visited[v] = 1;
printf("%d\n",v + 1);
while (ptr) {
j = ptr->tailvex;
doDFS(vertexs, m, j);
ptr = ptr->outlink;
}
}
广度优先搜索
void BFS(int **matrix, int m) {
int i, j;
int front = 0, back = 0,que[M * M] = {0};
for (i = 0; i < M; i++) {
visited[i] = 0;
}
for (i = 0; i < m; i++) {
if (!visited[i]) {
visited[i] = 1;
printf("%d\n", i + 1);
que[back++] = i;
while (front < back) {
front++;
for ( j = 0; j < m; j++) {
if (!matrix[i][j]) {
continue;
}
if (!visited[i]) {
visited[i] = 1;
printf("%d\n", i + 1);
que[back++] = i;
}
}
}
}
}
}
十字链表:
void BFS(Vertex *vertexs, int m) {
int i, j;
int front = 0, back = 0,que[M * M] = {0};
Edge *ptr;
for (i = 0; i < M; i++) {
visited[i] = 0;
}
for (i = 0; i < m; i++) {
if (!visited[i]) {
visited[i] = 1;
printf("%d\n", i);
que[back++] = i;
while (front < back) {
front++;
ptr = vertexs[i].firstout;
while (ptr) {
if (!visited[i]) {
visited[i] = 1;
printf("%d\n", i);
que[back++] = i;
}
ptr = ptr->outlink;
}
}
}
}
}
完整源代码
邻接矩阵:
#include <stdio.h>
#define M 16
void getGraph(int **matrix, int *m) {
int i,j;
scanf("%d", m);
for (i = 0; i < *m; i++) {
for (j = 0; j < *m; j++) {
scanf("%d",&matrix[i][j]);
}
}
}
void putGraph(int **matrix, int m) {
int i, j;
for (i = 0; i < m; i++) {
for (j = 0; j < m; j++) {
printf("%d ", matrix[i][j]);
}
putchar('\n');
}
}
int visited[M];
void DFS(int **matrix, int m) {
int i;
for (i = 0; i < M; i++) {
visited[i] = 0;
}
for (i = 0; i < m; i++) {
if (!visited[i]) {
doDFS(matrix,m,i);
}
}
}
void doDFS(int **matrix, int m, int v) {
int i;
visited[v] = 1;
printf("%d\n",v + 1);
for (i = 0; i < m; i++) {
if (matrix[v][i]) {
if (!visited[i]) {
doDFS(matrix, m, i);
}
}
}
}
void BFS(int **matrix, int m) {
int i, j;
int front = 0, back = 0,que[M * M] = {0};
for (i = 0; i < M; i++) {
visited[i] = 0;
}
for (i = 0; i < m; i++) {
if (!visited[i]) {
visited[i] = 1;
printf("%d\n", i + 1);
que[back++] = i;
while (front < back) {
front++;
for ( j = 0; j < m; j++) {
if (!matrix[i][j]) {
continue;
}
if (!visited[i]) {
visited[i] = 1;
printf("%d\n", i + 1);
que[back++] = i;
}
}
}
}
}
}
int main() {
int m = 2, matrix[M][M] = {0};
getGraph(matrix, &m);
DFS(matrix, m);
BFS(matrix, m);
}
十字链表:
#include <stdio.h>
#include <stdlib.h>
#define M 16
typedef struct Edge {
int headvex;
int tailvex;
struct Edge *outlink;
struct Edge *inlink;
int val;
} Edge;
typedef struct {
int val;
Edge *firstin;
Edge *firstout;
} Vertex;
void appendInEdge(Vertex *vertex, Edge *edge) {
Edge *ptr;
edge->inlink = NULL;
if(vertex->firstin) {
ptr = vertex->firstin;
while(ptr->inlink) {
ptr = ptr->inlink;
}
ptr->inlink = edge;
}
else {
vertex->firstin = edge;
}
}
void appendOutEdge(Vertex *vertex, Edge *edge) {
Edge *ptr;
edge->outlink = NULL;
if(vertex->firstout) {
ptr = vertex->firstout;
while(ptr->outlink) {
ptr = ptr->outlink;
}
ptr->outlink = edge;
}
else {
vertex->firstout = edge;
}
}
void getOList(Vertex *vertexs, int m) {
int i, j, k;
Edge *edge;
for (i = 0; i < m; i++) {
vertexs[i].firstin = NULL;
vertexs[i].firstout = NULL;
}
while (scanf("%d %d", &i, &j) != EOF) {
//append
edge = (Edge *)malloc(sizeof(Edge));
edge->headvex = i;
edge->tailvex = j;
appendOutEdge(&vertexs[i], edge);
appendInEdge (&vertexs[j], edge);
}
}
int getEdge(Vertex *vertexs, int x, int y) {
Edge *ptr;
ptr = vertexs[x].firstout;
while (ptr) {
if (ptr->tailvex == y) {
return ptr->val;
}
}
return -1;
}
void putOList(Vertex *vertexs, int m) {
int i, j;
Edge *ptr;
//in
for (j = 0; j < m; j++) {
ptr = vertexs[j].firstin;
while (ptr) {
i = ptr->headvex;
printf("%d %d\n", i, j);
ptr = ptr->inlink;
}
}
printf("out:\n");
//out
for (i = 0; i < m; i++) {
ptr = vertexs[i].firstout;
while (ptr) {
j = ptr->tailvex;
printf("%d %d\n",i , j);
ptr = ptr->outlink;
}
}
printf("\n");
}
int visited[M];
void DFS(Vertex *vertexs, int m) {
int i;
for (i = 0; i < M; i++) {
visited[i] = 0;
}
for (i = 0; i < m; i++) {
if (!visited[i]) {
doDFS(vertexs,m,i);
}
}
}
void doDFS(Vertex *vertexs, int m, int v) {
int j;
Edge *ptr = vertexs[v].firstout;
visited[v] = 1;
printf("%d\n",v + 1);
while (ptr) {
j = ptr->tailvex;
doDFS(vertexs, m, j);
ptr = ptr->outlink;
}
}
void BFS(Vertex *vertexs, int m) {
int i, j;
int front = 0, back = 0,que[M * M] = {0};
Edge *ptr;
for (i = 0; i < M; i++) {
visited[i] = 0;
}
for (i = 0; i < m; i++) {
if (!visited[i]) {
visited[i] = 1;
printf("%d\n", i);
que[back++] = i;
while (front < back) {
front++;
ptr = vertexs[i].firstout;
while (ptr) {
if (!visited[i]) {
visited[i] = 1;
printf("%d\n", i);
que[back++] = i;
}
ptr = ptr->outlink;
}
}
}
}
}
int main() {
int i, j, m;
Vertex vertexs[M];
scanf("%d",&m);
getOList(vertexs, m);
putOList(vertexs, m);
BFS(vertexs,m);
return 0;
}