1 /*
2  * Copyright 2015-2018 HuntLabs.cn
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 module hunt.sql.util.ListDG;
17 import std.stdio;
18 import hunt.collection;
19 //import hunt.lang;
20 import hunt.sql.util.Utils;
21 import hunt.sql.util.FnvHash;
22 
23 /**
24  * Java: 无回路有向图(Directed Acyclic Graph)的拓扑排序
25  *       该DAG图是通过邻接表实现的。
26  *
27  */
28 
29 
30 public class ListDG {
31     public static class Edge {
32         public Object from;
33         public Object to;
34 
35         public this(Object from, Object to) {
36             this.from = from;
37             this.to = to;
38         }
39     }
40 
41     // 邻接表中表对应的链表的顶点
42     private class ENode {
43         int ivex;       // 该边所指向的顶点的位置
44         ENode nextEdge; // 指向下一条弧的指针
45     }
46 
47     // 邻接表中表的顶点
48     private class VNode {
49         Object data;          // 顶点信息
50         ENode firstEdge;    // 指向第一条依附该顶点的弧
51     };
52 
53     private List!(VNode) mVexs;  // 顶点数组
54 
55     /*
56      * 创建图(用已提供的矩阵)
57      *
58      * 参数说明:
59      *     vexs  -- 顶点数组
60      *     edges -- 边数组
61      */
62     public this(List!Object vexs, List!(Edge) edges) {
63 
64         // 初始化"顶点数"和"边数"
65         int vlen = vexs.size();
66         int elen = edges.size();
67 
68         // 初始化"顶点"
69         mVexs = new ArrayList!(VNode)();
70         for (int i = 0; i < vlen; i++) {
71             // 新建VNode
72             VNode vnode = new VNode();
73             vnode.data = vexs.get(i);
74             vnode.firstEdge = null;
75             // 将vnode添加到数组mVexs中
76             mVexs.add(vnode);
77         }
78 
79         // 初始化"边"
80         for (int i = 0; i < elen; i++) {
81             // 读取边的起始顶点和结束顶点
82             Object c1 = edges.get(i).from;
83             Object c2 = edges.get(i).to;
84             // 读取边的起始顶点和结束顶点
85             int p1 = getPosition(edges.get(i).from);
86             int p2 = getPosition(edges.get(i).to);
87 
88             // 初始化node1
89             ENode node1 = new ENode();
90             node1.ivex = p2;
91             // 将node1链接到"p1所在链表的末尾"
92             if(mVexs.get(p1).firstEdge is null)
93                 mVexs.get(p1).firstEdge = node1;
94             else
95                 linkLast(mVexs.get(p1).firstEdge, node1);
96         }
97     }
98 
99     /*
100      * 将node节点链接到list的最后
101      */
102     private void linkLast(ENode list, ENode node) {
103         ENode p = list;
104 
105         while(p.nextEdge !is null)
106             p = p.nextEdge;
107         p.nextEdge = node;
108     }
109 
110     /*
111      * 返回ch位置
112      */
113     private int getPosition(Object ch) {
114         for(int i=0; i<mVexs.size(); i++)
115             if(mVexs.get(i).data == ch)
116                 return i;
117         return -1;
118     }
119 
120     /*
121      * 深度优先搜索遍历图的递归实现
122      */
123     private void DFS(int i, bool[] visited) {
124         ENode node;
125 
126         visited[i] = true;
127         node = mVexs.get(i).firstEdge;
128         while (node !is null) {
129             if (!visited[node.ivex])
130                 DFS(node.ivex, visited);
131             node = node.nextEdge;
132         }
133     }
134 
135     /*
136      * 深度优先搜索遍历图
137      */
138     public void DFS() {
139         bool[] visited = new bool[mVexs.size()];       // 顶点访问标记
140 
141         // 初始化所有顶点都没有被访问
142         for (int i = 0; i < mVexs.size(); i++)
143             visited[i] = false;
144 
145         for (int i = 0; i < mVexs.size(); i++) {
146             if (!visited[i])
147                 DFS(i, visited);
148         }
149     }
150 
151     /*
152      * 广度优先搜索(类似于树的层次遍历)
153      */
154     public void BFS() {
155         int head = 0;
156         int rear = 0;
157         int[] queue = new int[mVexs.size()];            // 辅组队列
158         bool[] visited = new bool[mVexs.size()];  // 顶点访问标记
159 
160         for (int i = 0; i < mVexs.size(); i++)
161             visited[i] = false;
162 
163         for (int i = 0; i < mVexs.size(); i++) {
164             if (!visited[i]) {
165                 visited[i] = true;
166                 writefln("%c ", mVexs.get(i).data);
167                 queue[rear++] = i;  // 入队列
168             }
169 
170             while (head != rear) {
171                 int j = queue[head++];  // 出队列
172                 ENode node = mVexs.get(j).firstEdge;
173                 while (node !is null) {
174                     int k = node.ivex;
175                     if (!visited[k])
176                     {
177                         visited[k] = true;
178                         writefln("%c ", mVexs.get(k).data);
179                         queue[rear++] = k;
180                     }
181                     node = node.nextEdge;
182                 }
183             }
184         }
185     }
186 
187     /*
188      * 打印矩阵队列图
189      */
190     public void print() {
191         writefln("== List Graph:\n");
192         for (int i = 0; i < mVexs.size(); i++) {
193             writefln("%d(%c): ", i, mVexs.get(i).data);
194             ENode node = mVexs.get(i).firstEdge;
195             while (node !is null) {
196                 writefln("%d(%c) ", node.ivex, mVexs.get(node.ivex).data);
197                 node = node.nextEdge;
198             }
199         }
200     }
201 
202     public bool topologicalSort() {
203         return topologicalSort(new Object[mVexs.size()]);
204     }
205 
206     /*
207      * 拓扑排序
208      *
209      * 返回值:
210      *     true 成功排序,并输入结果
211      *     false 失败(该有向图是有环的)
212      */
213     public bool topologicalSort(Object[] tops) {
214         int index = 0;
215         int num = mVexs.size();
216         int[] ins;               // 入度数组
217         //Object[] tops;             // 拓扑排序结果数组,记录每个节点的排序后的序号。
218         LinkedList!(int) queue = new LinkedList!(int)();    // 辅组队列
219 
220         ins   = new int[num];
221         //tops  = new Object[num];
222         // 统计每个顶点的入度数
223         for(int i = 0; i < num; i++) {
224 
225             ENode node = mVexs.get(i).firstEdge;
226             while (node !is null) {
227                 ins[node.ivex]++;
228                 node = node.nextEdge;
229             }
230         }
231 
232         // 将所有入度为0的顶点入队列
233         for(int i = 0; i < num; i ++)
234             if(ins[i] == 0)
235                 queue.addLast(i);                 // 入队列
236 
237         while (!queue.isEmpty()) {              // 队列非空
238             int j = queue.removeFirst();    // 出队列。j是顶点的序号
239             tops[index++] = mVexs.get(j).data;  // 将该顶点添加到tops中,tops是排序结果
240             ENode node = mVexs.get(j).firstEdge;// 获取以该顶点为起点的出边队列
241 
242             // 将与"node"关联的节点的入度减1;
243             // 若减1之后,该节点的入度为0;则将该节点添加到队列中。
244             while(node !is null) {
245                 // 将节点(序号为node.ivex)的入度减1。
246                 ins[node.ivex]--;
247                 // 若节点的入度为0,则将其"入队列"
248                 if( ins[node.ivex] == 0)
249                     queue.addLast(node.ivex);    // 入队列
250 
251                 node = node.nextEdge;
252             }
253         }
254 
255         if(index != num) {
256             return false;
257         }
258 
259         return true;
260     }
261 
262 //    public static void main(string[] args) {
263 //        Object[] vexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
264 //        Edge[] edges = new Edge[]{
265 //                new Edge(vexs[0], vexs[6]),
266 //                new Edge(vexs[1], vexs[0]),
267 //                new Edge(vexs[1], vexs[3]),
268 //                new Edge(vexs[2], vexs[5]),
269 //                new Edge(vexs[2], vexs[6]),
270 //                new Edge(vexs[3], vexs[4]),
271 //                new Edge(vexs[3], vexs[5])};
272 //        ListDG pG;
273 //
274 //        // 自定义"图"(输入矩阵队列)
275 //        //pG = new ListDG();
276 //        // 采用已有的"图"
277 //        pG = new ListDG(Arrays.asList(vexs), Arrays.asList(edges));
278 //
279 //        pG.print();   // 打印图
280 //        //pG.DFS();     // 深度优先遍历
281 //        //pG.BFS();     // 广度优先遍历
282 //        pG.topologicalSort();     // 拓扑排序
283 //    }
284 }