图的存储与遍历

图的存储

邻接矩阵

图是一种多对多的数据结构,对于一个有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;
}
posted @ 2016-03-02 20:23  -Finley-  阅读(546)  评论(0编辑  收藏  举报