word_components.w
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:5k
源码类别:

通讯编程

开发平台:

Visual C++

  1. % This file is part of the Stanford GraphBase (c) Stanford University 1993
  2. @i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES!
  3. @i gb_types.w
  4. deftitle{WORD_,COMPONENTS}
  5. prerequisite{GB_WORDS}
  6. @* Components. kern-.7pt
  7. This simple demonstration program computes the connected
  8. components of the GraphBase graph of five-letter words. It prints the
  9. words in order of decreasing weight, showing the number of edges,
  10. components, and isolated vertices present in the graph defined by the
  11. first $n$ words for all~$n$.
  12. @p
  13. #include "gb_graph.h" /* the GraphBase data structures */
  14. #include "gb_words.h" /* the |words| routine */
  15. @h@#@;
  16. main()
  17. {@+Graph *g=words(0L,0L,0L,0L); /* the graph we love */
  18.   Vertex *v; /* the current vertex being added to the component structure */
  19.   Arc *a; /* the current arc of interest */
  20.   long n=0; /* the number of vertices in the component structure */
  21.   long isol=0; /* the number of isolated vertices in the component structure */
  22.   long comp=0; /* the current number of components */
  23.   long m=0; /* the current number of edges */
  24.   printf("Component analysis of %sn",g->id);
  25.   for (v=g->vertices; v<g->vertices+g->n; v++) {
  26.     n++, printf("%4ld: %5ld %s",n,v->weight,v->name);
  27.     @<Add vertex |v| to the component structure, printing out any
  28.           components it joins@>;
  29.     printf("; c=%ld,i=%ld,m=%ldn", comp, isol, m);
  30.   }
  31.   @<Display all unusual components@>;
  32.   return 0; /* normal exit */
  33. }
  34. @ The arcs from |v| to previous vertices all appear on the list |v->arcs|
  35. after the arcs from |v| to future vertices. In this program, we aren't
  36. interested in the future, only the past; so we skip the initial arcs.
  37. @<Add vertex |v| to the component structure...@>=
  38. @<Make |v| a component all by itself@>;
  39. a=v->arcs;
  40. while (a && a->tip>v) a=a->next;
  41. if (!a) printf("[1]"); /* indicate that this word is isolated */
  42. else {@+long c=0; /* the number of merge steps performed because of |v| */
  43.   for (; a; a=a->next) {@+register Vertex *u=a->tip;
  44.     m++;
  45.     @<Merge the components of |u| and |v|, if they differ@>;
  46.   }
  47.   printf(" in %s[%ld]", v->master->name, v->master->size);
  48.    /* show final component */
  49. }
  50. @ We keep track of connected components by using circular lists, a
  51. procedure that is known to take average time $O(n)$ on truly
  52. random graphs [Knuth and Sch"onhage, {sl Theoretical Computer Science/
  53. @^Knuth, Donald Ervin@>
  54. @^Sch"onhage, Arnold@>
  55. bf 6}  (1978), 281--315].
  56. Namely, if |v| is a vertex, all the vertices in its component will be
  57. in the list
  58. $$hbox{|v|,  |v->link|,  |v->link->link|,  dots,}$$
  59. eventually returning to |v| again. There is also a master vertex in
  60. each component, |v->master|; if |v| is the master vertex, |v->size| will
  61. be the number of vertices in its component.
  62. @d link z.V /* link to next vertex in component (occupies utility field |z|) */
  63. @d master y.V /* pointer to master vertex in component */
  64. @d size x.I /* size of component, kept up to date for master vertices only */
  65. @<Make |v| a component all by itself@>=
  66. v->link=v;
  67. v->master=v;
  68. v->size=1;
  69. isol++;
  70. comp++;
  71. @ When two components merge together, we change the identity of the master
  72. vertex in the smaller component. The master vertex representing |v| itself
  73. will change if |v| is adjacent to any prior vertex.
  74. @<Merge the components of |u| and |v|, if they differ@>=
  75. u=u->master;
  76. if (u!=v->master) {@+register Vertex *w=v->master, *t;
  77.   if (u->size<w->size) {
  78.     if (c++>0) printf("%s %s[%ld]", (c==2? " with": ","), u->name, u->size);
  79.     w->size += u->size;
  80.     if (u->size==1) isol--;
  81.     for (t=u->link; t!=u; t=t->link) t->master=w;
  82.     u->master=w;
  83.   }@+else {
  84.     if (c++>0) printf("%s %s[%ld]", (c==2? " with": ","), w->name, w->size);
  85.     if (u->size==1) isol--;
  86.     u->size += w->size;
  87.     if (w->size==1) isol--;
  88.     for (t=w->link; t!=w; t=t->link) t->master=u;
  89.     w->master=u;
  90.   }
  91.   t=u->link;
  92.   u->link=w->link;
  93.   w->link=t;
  94.   comp--;
  95. }
  96. @ The |words| graph has one giant component and lots of isolated vertices.
  97. We consider all other components unusual, so we print them out when the
  98. other computation is done.
  99. @<Display all unusual components@>=
  100. printf(
  101.   "nThe following non-isolated words didn't join the giant component:n");
  102. for (v=g->vertices; v<g->vertices+g->n; v++)
  103.   if (v->master==v && v->size>1 && v->size+v->size<g->n) {@+register Vertex *u;
  104.      long c=1; /* count of number printed on current line */
  105.      printf("%s", v->name);
  106.      for (u=v->link; u!=v; u=u->link) {
  107.        if (c++==12) putchar('n'),c=1;
  108.        printf(" %s",u->name);
  109.      }
  110.      putchar('n');
  111.   }
  112. @* Index. We close with a list that shows where the identifiers of this
  113. program are defined and used.