-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathworkflow_test.cpp
More file actions
241 lines (202 loc) · 15.4 KB
/
workflow_test.cpp
File metadata and controls
241 lines (202 loc) · 15.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#include "workflow.h"
pNodeMap initialmap() {
pNodeMap map=(pNodeMap)calloc(sizeof(NodeMap),1);
return map;
}
int NODEMAP_addnode(pNodeMap map,char* node_text) {
if(!map) return -1;
/*
* 如果没有 node_list , 先初始化20个
*/
if(!map->node_list) {
map->node_list=(pFlowNode)calloc(sizeof(FlowNode),20);
if(!map->node_list) return -1;
}
int node_mem_size=_msize(map->node_list)/sizeof(FlowNode);
if(map->node_count>=node_mem_size) {
/*
* 扩容
*/
map->node_list=(pFlowNode)realloc(map->node_list,(node_mem_size+20)*sizeof(FlowNode));
if(!map->node_list) return -1;
}
if(map->node_count==0) map->id_sequence=0;
map->node_list[map->node_count].id=(++map->id_sequence);
strcpy(map->node_list[map->node_count].text,node_text);
map->node_count++;
return 0;
}
int NODEMAP_removenode(pNodeMap map,int nodeid) {
return -1;
}
int NODEMAP_connect(pNodeMap map,int prenodeid,int nodeid) {
if(!map) return -1;
if(!map->conn_list) {
map->conn_list=(pNodeConn)calloc(sizeof(NodeConn),20*20);
}
if(!map->conn_list) return -1;
int conn_mem_size=_msize(map->conn_list)/sizeof(NodeConn);
if(conn_mem_size<=map->conn_count) {
map->conn_list=(pNodeConn)realloc(map->conn_list,sizeof(NodeConn)*conn_mem_size+20);
if(!map->conn_list) return -1;
}
map->conn_list[map->conn_count].preid=prenodeid;
map->conn_list[map->conn_count].nextid=nodeid;
map->conn_list[map->conn_count].connect=1;
map->conn_count++;
return 0;
}
int NODEMAP_disconnect(pNodeMap map,int prenodeid,int nodeid) {
return -1;
}
/*
* 功能: 生成最新的map信息
*
* pNodeMap 根据存储的node 和 connection 信息
* 生成一张完整的 map
* 注意map可能随时生成,一旦有新的节点或者连接加入/删除,map 可能就会发生改变
* ----------------------------------------------------------------------------
* 问题1. 如果连通的两个节点,位于相邻的两层,比较简单,但是如果连通的两个节点跨越了层,算法该如何计算行列?
* 如下图, E到底应该放在什么位置?
* A A
* +-------+ +-------+
* | | | |
* B---+ | B---+ E(2)
* | | | | | |
* | | | | | |
* C D E(1) C D |
* | | | | | |
* | | | | | |
* +---+---+ +---+---+
* | |
* | |
* F F
*/
/*
* 思路1:
* 1.找出所有没有前驱的节点,定义为第一层
* 2.从剩余节点中查找遍历每一个节点,如果前驱为第一层的节点,该节点的层级定义为 上层层级+1,
* 在完成上一层所有节点的遍历后,以层级最大值定义为该节点的层级
* 3.循环,直到所有节点都定义层级
*
*/
int qs_cmp_nodeid(const void* a,const void* b) { int id_a=*((int*)a); int id_b=*((int*)b); return id_a-id_b; }
int qs_cmp_nodelv(const void* a,const void* b) { int id_a=*((int*)a+1); int id_b=*((int*)b+1); return id_a-id_b; }
int bs_cmp_nodeid(const void* a,const void* b) { return (*(int*)a)-(*(int*)b); }
int NODEMAP_map(pNodeMap map) {
if(!map||!map->node_list||!map->conn_list) return -1;
//1.提取所有的节点ID
int* id_array=(int*)calloc(sizeof(int)*map->node_count*2,1);
if(!id_array) return -1;
for(int idx=0;idx<map->node_count;idx++) id_array[idx*2]=map->node_list[idx].id;
//排序一遍查找
qsort(id_array,map->node_count,sizeof(int)*2,qs_cmp_nodeid);
//2.确定每个节点的层级
for(int idx=0;idx<map->node_count;idx++) {
NODEMAP_map_calc_level(id_array[idx*2],id_array,map->node_count,map->conn_list,map->conn_count);
}
//3.确定每个层级的列序
//重新对id_array排序,按照 level
qsort(id_array,map->node_count,sizeof(int)*2,qs_cmp_nodelv);
if(map->levels) {
for(int idx=0;idx<map->rows;idx++) {
pNMLevel pL=map->levels+idx;
if(pL->pos) free(pL->pos);
}
//删除重新分配
free(map->levels);
map->levels=NULL;
}
//最大层级
int maxlevel=id_array[(map->node_count-1)*2+1];
/*
* 注意:如果没有零层,map->rows=maxlevel;
* 否则 map->rows=maxlevel+1;
*/
//map->rows=maxlevel+1;//没连通的节点视为第0层
if (id_array[1] > 0) {
map->rows = maxlevel;
}
else map->rows=maxlevel+1;
map->levels=(pNMLevel)calloc(sizeof(NMLevel)*(map->rows+1),1);
if(!map->levels) return -1; //有点问题
int i_cols=0;
for(int idx=0;idx<=map->rows;idx++) {
map->levels[idx].level_idx=idx;
int i_begin=i_cols;
for(;i_cols<map->node_count;i_cols++) {
if(id_array[i_cols*2+1]!=map->levels[idx].level_idx) break;
}
map->levels[idx].count=i_cols-i_begin;
map->levels[idx].pos=(int*)calloc(sizeof(int)*2,map->levels[idx].count);
memcpy(map->levels[idx].pos,id_array+i_begin*2,map->levels[idx].count*2*sizeof(int));
for(int col=0;col<map->levels[idx].count;col++) {
map->levels[idx].pos[col*2+1]=col;
}
if(map->cols<map->levels[idx].count) map->cols=map->levels[idx].count;
}
if(id_array) free(id_array);
return 0;
}
/*
* 反向更新 node level
*/
void NODEMAP_map_reverse_level(int id, int level,int* id_array, int node_count, pNodeConn conn_list, int conn_count) {
for(int idx=0;idx<conn_count;idx++) {
if(conn_list[idx].connect==1&&id==conn_list[idx].nextid) {
int* preid_addr=(int*)bsearch(&conn_list[idx].preid, id_array, node_count, sizeof(int) * 2, bs_cmp_nodeid);
if(!preid_addr) return;
int preid_level=*(preid_addr+1);
if(preid_level<level-1) {
*(preid_addr+1)=level-1;
NODEMAP_map_reverse_level(*preid_addr, *(preid_addr + 1), id_array, node_count, conn_list, conn_count);
}
}
}
}
void NODEMAP_map_calc_level(int id,int* id_array,int node_count,pNodeConn conn_list,int conn_count) {
for(int idx=0;idx<conn_count;idx++) {
if(conn_list[idx].connect==1&&id==conn_list[idx].preid) {
int* preid_addr=(int*)bsearch(&conn_list[idx].preid,id_array,node_count,sizeof(int)*2,bs_cmp_nodeid);
if(!preid_addr) return;
if(*(preid_addr+1)==0) *(preid_addr+1)=1;//第一层
int* nextid_addr=(int*)bsearch(&conn_list[idx].nextid,id_array,node_count,sizeof(int)*2,bs_cmp_nodeid);
if(!nextid_addr) return;
//if(*(nextid_addr+1)==0) {
//if(*(nextid_addr+1)<)
int pre_level=*(preid_addr+1);
int next_level=*(nextid_addr+1);
if(pre_level+1>next_level) {
*(nextid_addr+1)=pre_level+1;
/*
* 需要倒回去更改其所有前驱
* 如果前驱的level<当前节点的level-1 , 需要递归更新 前驱节点的 level = 当前节点的 level-1;
* 否则 不处理
*/
NODEMAP_map_reverse_level(*nextid_addr,*(nextid_addr+1),id_array,node_count,conn_list,conn_count);
}
//}
NODEMAP_map_calc_level(conn_list[idx].nextid,id_array,node_count,conn_list,conn_count);
}
}
}
void NODEMAP_release(pNodeMap map) {
if(!map) return;
if(map->levels) {
for(int idx=0;idx<map->rows;idx++) {
pNMLevel pL=map->levels+idx;
if(pL->pos) free(pL->pos);
}
free(map->levels);
map->levels=NULL;
}
if(map->node_list) {
free(map->node_list);
map->node_list=NULL;
}
if(map->conn_list) {
free(map->conn_list);
map->conn_list=NULL;
}
free(map);
}