图的存储和遍历

 
图是一种复杂的非线性结构,其中任意两个节点都可能相连.图G一般由顶点集合V和边集合E组成.E由V中顶点的偶对组成,表示为 G(V,E).
图有多重存储结构, 常用的有 邻接矩阵、 临接表、 逆临接表、 十字链表。 本篇以临接矩阵和临接表方式演示

实现代码如下:
  1 public class Graph {
  2     //标记节点是否已访问过了
  3     private boolean[] isVisit = {false,false,false,false,false,false,false,false,false,false};
  4 
  5     public static void main(String[] args) {
  6         new Graph().table();
  7     }
  8 
  9     /**
 10      * 
 11      * @Title: matrix  
 12      * @Description: TODO 图的邻接矩阵表示
 13      * @param     设定文件  
 14      * @return void    返回类型  
 15      * @throws
 16      */
 17     public  void matrix() {
 18 
 19         //顶点表
 20         Node[] nodes = {new Node(0),new Node(1),new Node(2),new Node(3),new Node(4)};
 21 
 22 
 23 
 24         //无向图的临接矩阵存储,对称矩阵,这个矩阵描述了图的边集合
 25         //边表, 不带权,i表示行标, j表示列标.第i行表示第i个定点(i对应nodes顶点的key值和下标),
 26         //第i个节点指向的节点key 作为j的下标, 赋值1,表示有连接
 27         int[][] table = {
 28                 {0, 1, 0, 1, 0},//第0号定点指向了第1号节点和第3号节点
 29                 {1, 0, 0, 1, 0},
 30                 {0, 0, 0, 0, 0},
 31                 {1, 1, 0, 0, 1},
 32                 {0, 0, 0, 1, 0},
 33         };
 34 
 35         //有向图,
 36         //第i行的非0节点,表示顶点i的出度
 37         //第i列的非0节点,表示顶点i的入度
 38         //定点不能指向自己,主对角线为0
 39         int[][] table2 = {
 40                 {0, 1, 0, 1, 0},//第0号节点指向了第1号节点和第3号节点
 41                 {1, 0, 0, 0, 1},
 42                 {0, 0, 0, 0, 0},
 43                 {1, 0, 1, 0, 1},
 44                 {0, 1, 0, 1, 0},
 45         };
 46 
 47         //对于带权边的表示:用权值替换1,用MAX_VALUE替换0
 48     }
 49 
 50     /**
 51      * 
 52      * @Title: table  
 53      * @Description: TODO 图的临接表表示
 54      * @param     设定文件  
 55      * @return void    返回类型  
 56      * @throws
 57      */
 58     public  void table() {
 59 
 60         //临接表表示法类似与 HashMap 的存储结构.数组与链表组合.数组的每个节点都是一个链表的头结点
 61         //顶点表
 62         Vertex_node[] nodes = {new Vertex_node(0),new Vertex_node(1),new Vertex_node(2),new Vertex_node(3),new Vertex_node(4)};
 63 
 64         //有向图
 65         nodes[0].head = new Side_node(1,new Side_node(4,null));//指向1号和4号节点
 66         nodes[1].head = new Side_node(2,new Side_node(3,null));//指向3号和2号节点
 67         nodes[2].head = new Side_node(1,null);                   //指向1号节点
 68         nodes[3].head = new Side_node(0,new Side_node(4,null));//指向0/4号节点
 69         nodes[4].head = new Side_node(1,null);                    //指向1号节点
 70 
 71         //数组元素表示顶点,数组元素的链表,表示这个元素的边集合
 72         
 73         //每个顶点的初度是边表的长度
 74         //入度需要扫描整个临接表,
 75 
 76         //对于带权边的表示:需要在 side_node 类中添加一个 value 域,存放权值
 77 
 78 
 79         printGraph(nodes);
 80 
 81         //图的遍历
 82         //深度优先搜素
 83 
 84 
 85         //深度优先搜索
 86         System.out.println("深度优先搜索");
 87         DFS(nodes,0);
 88 
 89         for(int i = 0; i < isVisit.length; i++) {
 90             isVisit[i] = false;
 91         }
 92 
 93         //广度优先搜索
 94         System.out.println("广度优先搜索");
 95         BFS(nodes,0);
 96 
 97 
 98 
 99 
100 
101     }
102 
103     /**
104      * @Title: BFS  
105      * @Description: TODO 广度优先搜索   
106      * @param @param nodes 邻接表方式存储的 顶点集合
107      * @param @param index 第一个访问的顶点,index应小于nodes.length 
108      * @return void    返回类型  
109      * @throws
110      */
111     private void BFS(Vertex_node[] nodes, int index) {
112         //队列用LinkedList
113         Queue<Integer> queue = new LinkedList<Integer>();
114 
115 
116 
117         //访问第一个节点
118         if(index >= 0 && index < nodes.length) {
119 
120             isVisit[index] = true;
121             System.out.println("visited :"+nodes[index].key);
122             queue.add(nodes[index].key);//入队
123         }
124 
125         //循环条件是队列不为null
126         while(!queue.isEmpty()) {
127             int idx = queue.poll();//出队
128 
129             Side_node n = nodes[idx].head;
130             while(n != null) {
131 
132                 //                if the node is not visited, visit that and add that to queue 
133                 if(!isVisit[n.key]) {
134                     //visite
135                     isVisit[n.key] = true;
136                     System.out.println("visited :"+n.key);
137                     //入队列
138                     queue.add(n.key);
139                 }
140 
141                 n = n.next;
142 
143             }
144 
145 
146         }
147 
148     }
149 
150 
151 
152     /**
153      * 
154      * @Title: DFS  
155      * @Description: TODO 深度优先搜索  
156      * @param @param nodes 邻接表方式存储的 顶点集合   
157      * @param @param index 第一个访问的顶点,index应小于nodes.length
158      * @return void    返回类型  
159      * @throws
160      */
161     private void DFS(Vertex_node[] nodes, int index) {
162         //节点 index 是否已访问
163         if(isVisit[index] || index >= nodes.length) {
164             return;
165         }
166         //访问,  --print
167         isVisit[index] = true;
168         System.out.println("visited :"+nodes[index].key);
169 
170         //递归nodes[index]出度节点
171         Side_node n = nodes[index].head;
172         while(n != null) {
173             if(!isVisit[n.key])
174                 DFS(nodes, n.key);
175             n = n.next;
176 
177         }
178 
179     }
180 
181     private void printGraph(Vertex_node[] nodes) {
182         // TODO Auto-generated method stub
183         for(Vertex_node n : nodes) {
184             System.out.print(n.key+":--> ");
185 
186             Side_node n1 = n.head;
187             while(n1 != null) {
188                 System.out.print(n1.key+" --> ");
189                 n1 = n1.next;
190 
191             }
192 
193             System.out.println();
194         }
195 
196     }
197 
198     class Node{
199         public int key;//节点的名称.比如第key号节点,不可重复
200         public int value;//权值
201 
202         public Node(int key) {
203             super();
204             this.key = key;
205         }
206         public Node(int key, int value) {
207             super();
208             this.key = key;
209             this.value = value;
210         }
211         public Node() {
212         }
213 
214 
215     }
216 
217 
218     /**
219      * 
220      * @ClassName: Vertex_node 
221      * @Description: TODO 临接表表示方式的 顶点类
222      * @author: zw
223      * @date: 2018年3月26日 下午3:17:46
224      */
225     class Vertex_node{
226         public int key;//节点的名称.比如第key号节点,不可重复
227 
228         public Side_node head;//出度链表的首结点
229 
230         public Vertex_node(int key) {
231             super();
232             this.key = key;
233         }
234         public Vertex_node(int key, Side_node head) {
235             super();
236             this.key = key;
237             this.head = head;
238         }
239         public Vertex_node() {
240         }
241 
242         
243     }
244 
245     /**
246      * 
247      * @ClassName: Side_node 
248      * @Description: TODO 临接表表示方式的 边表节点类
249      * @author: zw
250      * @date: 2018年3月26日 下午3:18:39
251      */
252     class Side_node{
253         public int key;//节点的名称.比如第key号节点,不可重复
254 
255         public Side_node next;//兄弟节点
256 
257         public Side_node(int key) {
258             super();
259             this.key = key;
260             this.next = null;
261         }
262         public Side_node(int key, Side_node next) {
263             super();
264             this.key = key;
265             this.next = next;
266         }
267         public Side_node() {
268         }
269 
270     }
271 }

 



输出结果
0:--> 1 --> 4 --> 
1:--> 2 --> 3 --> 
2:--> 1 --> 
3:--> 0 --> 4 --> 
4:--> 1 --> 
深度优先搜索
visited :0
visited :1
visited :2
visited :3
visited :4
广度优先搜索
visited :0
visited :1
visited :4
visited :2
visited :3

  

转载于:https://www.cnblogs.com/zhang01010/p/8655484.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值