zoukankan      html  css  js  c++  java
  • 图的存储与遍历

    图的存储

    邻接矩阵

    图是一种多对多的数据结构,对于一个有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
    ",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
    ",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
    ", 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
    ", 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
    ", i);
     		    que[back++] = i;
    	        while (front < back) {
                    front++;
                    ptr = vertexs[i].firstout;
                    while (ptr) {
                        if (!visited[i]) {
                            visited[i] = 1;
                            printf("%d
    ", 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('
    ');
    	}
    }
    
    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
    ",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
    ", 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
    ", 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
    ", i, j);
                  ptr = ptr->inlink;
               }
          }
          printf("out:
    ");
          //out
          for (i = 0; i < m; i++) {
               ptr = vertexs[i].firstout;
               while (ptr) {
                  j = ptr->tailvex;
                  printf("%d %d
    ",i , j);
                  ptr = ptr->outlink;
               }
          }
          printf("
    ");
    }
    
    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
    ",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
    ", i);
     		    que[back++] = i;
    	        while (front < back) {
                    front++;
                    ptr = vertexs[i].firstout;
                    while (ptr) {
                        if (!visited[i]) {
                            visited[i] = 1;
                            printf("%d
    ", 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;
    }
  • 相关阅读:
    HashMap 的实现原理(1.8)
    HashMap 的实现原理(1.7)
    Java面试总结 -2018(补录)
    在java中写出完美的单例模式
    ArrayList实现原理分析
    Ngigx+Tomcat配置动静分离,负载均衡
    微信小程序——常用快捷键【四】
    Linux服务器下安装vmware虚拟机
    微信小程序——部署云函数【三】
    微信小程序——安装开发工具和环境【二】
  • 原文地址:https://www.cnblogs.com/Finley/p/5236371.html
Copyright © 2011-2022 走看看