邻接表和邻接矩阵的相互转换
@Author: 张海拔
@Update: 2014-01-11
@Link: http://www.cnblogs.com/zhanghaiba/p/3515407.html
1 /* 2 *Author: ZhangHaiba 3 *Date: 2014-1-11 4 *File: mutual_conversion_adj_list_adj_mat.c 5 * 6 *a demo shows mutual conversion between adjacency list and adjacency matrix 7 */ 8 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #define N 512 13 typedef struct e_node* link; 14 15 typedef struct e_node { 16 int adjv; 17 link next; 18 }e_node; 19 20 typedef struct v_node { 21 int item; 22 link next; 23 }v_node; 24 25 //public 26 void init_adj_list(v_node*, int); 27 void create_adj_list(v_node*, int, int); 28 void show_adj_list(v_node*, int); 29 void destory_adj_list(v_node*, int); 30 void set_adj_mat(int); 31 void show_adj_mat(int); 32 void adj_mat_to_adj_list(v_node*, int); 33 void adj_list_to_adj_mat(v_node*, int); 34 //private 35 static link head_insert_node(link, int); 36 37 v_node list[N]; 38 int mat[N][N]; 39 40 int main(void) 41 { 42 int n, m; 43 44 //create adj_list, then convert adj_list into adj_mat 45 scanf("%d%d", &n, &m); 46 init_adj_list(list, n); 47 memset(mat, 0, sizeof mat); 48 create_adj_list(list, n, m); 49 adj_list_to_adj_mat(list, n); 50 show_adj_mat(n); 51 destory_adj_list(list, n); 52 53 //create adj_list, then convert adj_mat into adj_list 54 scanf("%d", &n); 55 memset(mat, 0, sizeof mat); 56 init_adj_list(list, n); 57 set_adj_mat(n); 58 adj_mat_to_adj_list(list, n); 59 show_adj_list(list, n); 60 destory_adj_list(list, n); 61 return 0; 62 } 63 64 void init_adj_list(v_node* a, int n) 65 { 66 int i; 67 68 for (i = 0; i < n; ++i) 69 a[i].next = NULL; 70 } 71 72 link head_insert_node(link h, int v) 73 { 74 link p = malloc(sizeof (e_node)); 75 p->adjv = v; 76 link save = h; 77 h = p; 78 p->next = save; 79 return h; 80 } 81 82 //for undirected graph 83 void create_adj_list(v_node* a, int n, int m) 84 { 85 //input edge info: (x, y) 86 int i, x, y; 87 88 for (i = 0; i < m; ++i) { 89 scanf("%d%d", &x, &y); 90 a[x].next = head_insert_node(a[x].next, y); 91 } 92 } 93 94 void show_adj_list(v_node* a, int n) 95 { 96 int i; 97 link p; 98 99 for (i = 0; i < n; ++i) { 100 printf("%d", i); 101 for (p = a[i].next; p != NULL; p = p->next) 102 printf("->%d", p->adjv); 103 printf("\n"); 104 } 105 } 106 107 void destory_adj_list(v_node* a, int n) 108 { 109 int i; 110 link p; 111 112 for (i = 0; i < n; ++i) 113 for (p = a[i].next; p != NULL; p = p->next) 114 free(p); 115 } 116 117 void set_adj_mat(int n) 118 { 119 int i, j; 120 121 for (i = 0; i < n; ++i) 122 for (j = 0; j < n; ++j) 123 scanf("%d", &mat[i][j]); 124 } 125 126 void show_adj_mat(int n) 127 { 128 int i, j; 129 130 for (i = 0; i < n; ++i) 131 for (j = 0; j < n; ++j) 132 printf(j == n-1 ? "%d\n" : "%d ", mat[i][j]); 133 } 134 135 void adj_mat_to_adj_list(v_node* a, int n) 136 { 137 int i, j; 138 139 for (i = 0; i < n; ++i) 140 for (j = n-1; j > -1; --j) 141 if (mat[i][j] > 0) 142 a[i].next = head_insert_node(a[i].next, j); 143 } 144 145 void adj_list_to_adj_mat(v_node* a, int n) 146 { 147 int i; 148 link p; 149 150 for (i = 0; i < n; ++i) { 151 for (p = a[i].next; p != NULL; p = p->next) 152 mat[i][p->adjv] = 1; 153 } 154 }
这里是针对有向图,而且忽略掉顶点的数据(如名字等),输入的边(x,y),x是按从小到大的顺序,同个x对应的y则是按从大到小的顺序。
测试用例
输入:
5 6
0 4
1 2
1 0
2 3
2 0
3 4
5
0 0 0 0 1
1 0 1 0 0
1 0 0 1 0
0 0 0 0 1
0 0 0 0 0
输出:
0 0 0 0 1
1 0 1 0 0
1 0 0 1 0
0 0 0 0 1
0 0 0 0 0
0->4
1->0->2
2->0->3
3->4
4
可以看到,如果熟悉邻接表的创建,这种相互转换是很容易的。
注意矩阵转邻接表时,为了满足上述“输入的边(x,y),x是按从小到大的顺序,同个x对应的y则是按从大到小的顺序”的要求,内层循环是按从大到小方向遍历的。
另外把头插法函数(创建邻接表函数的核心)单独写成一个函数,满足小即是美的设计。在这里的转换函数中更是得到了复用。