生成前缀集合和后缀集合时,对环状依赖的处理

由于在生成前后缀的时候,我们需要将这个文法符号按照拓扑排序来排列生成顺序,不过当语法里面有环的时候,一般的拓扑排序就无效了,这个时候需要采取将一个强联通区域的点汇聚在一起,也就是生成压缩图。课本上虽说强连通算法是线性时间,但是不写不知道,一写吓一跳,尼玛都快四次复杂度了有木有。

这里就贴一下生成强连通的代码

  1 void first_set_preprocess(void)//这个函数是用来消除强联通图,把强联通图直接短接,最后生成一个压缩图
  2 {
  3     first_graph_node** rev_first_graph;//这个当作逆转图的入口,因为我们要生成这个逆转图
  4     first_graph_node** new_first_graph;//这个当作原来的图的拷贝,因为在拓扑排序时会毁掉原来的图
  5     pfirst_graph_node temp_first_node,temp_first_add;
  6     pfirst_graph_node temp_pre_node,temp_after_node;,temp_node
  7     int dest_symbol;
  8     int for_i,for_j;
  9     int edge_number;
 10     int* merge_to_list;
 11     int* merge_from_list;//这两个变量是用来合并邻接表使用的
 12     int* already_out_stack;//表示第一遍遍历的时候哪些点已经出栈了
 13     int* already_in_stack;//表示第一遍遍历的时候哪些点在当前栈中
 14     int* already_in_group;//表示哪些点已经在第二次遍历的过程中处理过了
 15     int graph_index;//这个变量用来遍历原来的图
 16     int parent_index;
 17     int* begin_stack;
 18     int* end_stack;
 19     int begin_stack_index;
 20     int end_stack_index;
 21     int current_stack_top;
 22     begin_stack_index=end_stack_index=0;
 23     edge_number=number_edge_first;
 24     rev_first_graph=malloc(sizeof(int)*(node_index+2));
 25     new_first_graph=malloc(sizeof(int)*(node_index+2));
 26     already_in_stack=malloc(sizeof(int)*(node_index+2));
 27     already_out_stack=malloc(sizeof(int)*(node_index+2));
 28     merge_to_list=malloc(sizeof(int)*(node_index+2));
 29     merge_from_list=malloc(sizeof(int)*(node_index+2));
 30     already_in_group=malloc(sizeof(int)*(node_index+2));
 31     for(for_i=1;for_i<node_index+2;for_i++)
 32     {
 33         rev_first_graph[for_i]=NULL;
 34         new_first_graph[for_i]=NULL;
 35         parent_set[for_i]=for_i;
 36         merge_to_list[for_i]=0;
 37         merge_from_list[for_i]=0;
 38 
 39     }
 40     for(for_i=1;for_i<node_index+2;for_i++)
 41     {
 42         temp_first_node=first_graph[for_i];
 43         while(temp_first_node!=NULL)
 44         {
 45             dest_symbol=temp_first_node->first_symbol;
 46             temp_first_add=malloc(sizeof(struct _first_graph_node));
 47             temp_first_add->next=rev_first_graph[dest_symbol];
 48             temp_first_add->first_symbol=for_i;
 49             rev_first_graph[dest_symbol]=temp_first_add;
 50             temp_first_add=malloc(sizeof(struct _first_graph_node));
 51             temp_first_add->first_symbol=dest_symbol;
 52             temp_first_add->next=new_first_next[for_i];
 53             new_first_next[for_i]=temp_first_add;
 54             temp_first_node=temp_first_node->next;
 55         }
 56     }
 57     //两个临时的图都构建完成
 58     //现在开始第一次dfs,为了保留各个节点的结束顺序,我们刚好需要另外的一个栈来保存这些信息
 59     //因此我们需要两个栈 来完成第一次遍历
 60     //第二次遍历则需要哪些点已经完成了汇聚的信息,因此我们需要一个数组来表示哪些点已经完成了汇聚
 61     //同时第二次遍历需要的是深度优先遍历,这次我们可以复用原来的那个栈
 62     while(edge_number>0)
 63     {
 64         for_i=0;
 65         while(new_first_graph[for_i]==NULL)
 66         {
 67             for_i++;
 68         }
 69         begin_stack_index=1;
 70         begin_stack[1]=for_i;
 71         already_in_stack[for_i]=1;
 72         while(begin_stack_index>0)
 73         {
 74             current_stack_top=begin_stack[begin_stack_index]
 75             temp_first_node=new_first_graph[current_stack_top];
 76             if(temp_first_node==NULL)
 77             {
 78                 if(begin_stack_index!=1)
 79                 {
 80                     end_stack_index++;
 81                     end_stack[end_stack_index]=current_stack_top;
 82                     already_out_stack[current_stack_top]=1;
 83                     already_in_stack[current_stack_top]=0;
 84                     begin_stack_index--;
 85                 }
 86                 else
 87                 {
 88                     already_in_stack[current_stack_top]=0;
 89                     begin_stack_index--;
 90                 }
 91             }
 92             else
 93             {
 94                 dest_symbol=temp_first_node->first_symbol;
 95                 if(already_out_stack[dest_symbol]!=1)
 96                 {
 97                     if(already_in_stack[dest_symbol]!=1)
 98                     {
 99                         begin_stack_index++;
100                         begin_stack[begin_stack_index]=dest_symbol;
101                         already_in_stack[dest_symbol]=1;
102                     }
103 
104                 }
105                 new_first_graph[current_stack_top]=temp_first_node->next;
106                 edge_number--;
107                 free(temp_first_node);
108             }
109         }
110 
111 
112 
113 
114     }//现在全都按照结束序进入了第二个栈中
115     //现在开始第二遍深度优先遍历,不过跟前面的那次遍历有点不同。。。
116     //因为这次有了集合操作
117     while(end_stack_index>0)//只要栈里还有元素
118     {
119         current_stack_top=end_stack[end_stack_index];
120         end_stack_index--;
121         if(already_in_group[current_stack_top]!=1)
122         {
123             begin_stack_index=1;
124             begin_stack[begin_stack_index]=current_stack_top;
125             while(rev_first_graph[begin_stack[1]]!=NULL)
126             {
127                 temp_node=rev_first_graph[begin_stack[begin_stack_index]];
128                 dest_symbol=temp_node->first_symbol;
129                 if(already_in_group[dest_symbol]!=1)
130                 {
131                     if(already_in_stack[dest_symbol]!=1)
132                     {
133                         begin_stack_index++;
134                         begin_stack[begin_stack_index]=dest_symbol;
135                         already_in_stack[dest_symbol]=1;
136                     }
137                     else
138                     {
139                         parent_index=parent_set[dest_symbol];//找到所在群的代表节点
140                         while(begin_stack[begin_stack_index]!=parent_index)
141                         {
142                             //这里开始合并操作
143                             current_stack_top=begin_stack[begin_stack_index];
144                             temp_after_node=rev_first_graph[current_stack_top];
145                             temp_pre_node=NULL;
146                             //这里开始删除边了
147                             //下面把这两个边里面邻接表中互相连接的边删除,并减少边的数目
148                             //之后再把两者的邻接表合并,碰到重复的边也删除一个,并减少边的数目
149                             for(for_i=0;for_i<node_index+2;for_i++)
150                             {
151                                 merge_to_list[for_i]=0;
152                                 merge_from_list[for_i]=0;
153                             }
154                             while(temp_after_node!=NULL)
155                             {
156                                 if(parent_set[temp_after_node->first_symbol]==parent_index)
157                                 {
158                                     if(temp_pre_node==NULL)
159                                     {
160                                         rev_first_graph[current_graph_top]=temp_after_node->next;
161                                         free(temp_after_node);
162                                         temp_after_node=rev_first_graph[current_graph_top];
163                                         edge_number--;
164                                     }
165                                     else
166                                     {
167                                         temp_pre_node->next=temp_after_node->next;
168                                         free(temp_after_node);
169                                         temp_after_node=temp_pre_node->next;
170                                         edge_number--;
171                                     }
172                                 }
173                                 else
174                                 {
175                                     merge_from_list[temp_after_node->first_symbol]=1;
176                                     temp_pre_node=temp_after_node;
177                                     temp_after_node=temp_after_node->next;
178                                 }
179                             }
180                             temp_after_node=rev_first_graph[parent_index];
181                             temp_pre_node=NULL;
182                             while(temp_after_node!=NULL)
183                             {
184                                 if(parent_set[temp_after_node->first_symbol]==current_stack_top)
185                                 {
186                                     if(temp_pre_node==NULL)
187                                     {
188                                         rev_first_graph[current_graph_top]=temp_after_node->next;
189                                         free(temp_after_node);
190                                         temp_after_node=rev_first_graph[current_graph_top];
191                                         edge_number--;
192                                     }
193                                     else
194                                     {
195                                         temp_pre_node->next=temp_after_node->next;
196                                         free(temp_after_node);
197                                         temp_after_node=temp_pre_node->next;
198                                         edge_number--;
199                                     }
200                                 }
201                                 else
202                                 {
203                                     merge_to_list[temp_after_node->first_symbol]=1;
204                                     temp_pre_node=temp_after_node;
205                                     temp_after_node=temp_after_node->next;
206                                 }
207                             }
208                             for(for_i=1;for_i<node_index;for_i++)
209                             {
210                                 if(merge_to_list[for_i]==1)
211                                 {
212                                     if(merge_from_list[for_i]==1)
213                                     {
214                                         edge_number--;
215                                     }
216                                     else
217                                     {
218                                         temp_first_node_add=malloc(sizeof(strcut _first_graph_node));
219                                         temp_first_node_add->first_symbol=for_i;
220                                         temp_first_node_add->next=rev_first_graph[parent_index];
221                                         rev_first_graph[parent_index]=temp_first_node_add;
222                                         merge_to_list[for_i]=1;
223                                     }
224                                 }
225                             }//边合并完成
226                             //至此,邻接表合并完成
227                             //然后修改位置数组
228                             for(for_i=1;for_i<node_index+1;for_i++)
229                             {
230                                 if(parent_set[for_i]==current_stack_top)
231                                 {
232                                     parent_set[for_i]=parent_index;
233                                 }
234                             }//所属的群索引标记完成
235                             begin_stack_index--;
236                         }
237                     }
238                 }
239                 else
240                 {
241                     begin_stack_index++;
242                     begin_stack[begin_stack_index]=dest_symbol;
243                 }
244             }//当前栈底可达的点都已经被合并为一个群了
245             already_in_group[begin_stack[1]]=1;
246         }
247         else
248         {
249             //神马都不干 
250         }
251     }//所有的群都已经生成完毕了
252 }
原文地址:https://www.cnblogs.com/huangfeidian/p/3175466.html