今天讲图最基本的东西---储存;

一、邻接矩阵:a[i,j]:=...(指从点i到点j的距离);存储方便,但损耗空间太多,若有10000个点就不行了。

二、邻接表:

这里需要使用指针:

这需要逆向保存,代码如下:

 1 type
 2    point=^node;
 3    node=record
 4                 u,v:longint; //u是和该点有边连接的点,v指这条边的权值。
 5                 next:point;
 6              end;
 7 var
 8    n,m,x,y,j:longint;  //n是点的数量,m是边的数量
 9    a:array[1..maxn]of point;
10    p:point;//如果要调用的话,需要加上head指针,否则直接用,就回不到最初的地址
11 begin
12     readln(n,m);
13     for  i:=1 to m do
14        begin
15            readln(x,y,j);
16            new(p); p^.u:=y; p^.v:=a[x]; a[x]:=p;
17            new(p); p^.u:=x; p^.v:=a[y]; a[y]:=p;
18        end;
19 end.
20 //这样建的邻接表就和上图一样,大家可以手动尝试一下。 

 

三、一个特殊且非常漂亮的结构,并查集:

并查集可以管理元素分组,①.查询元素a、b是否在同一组;②.合并元素a、b所在的组

并查集可用数来储存(不是二叉树),优化时,可以将根节点以下的点全部指向根结点,使高度从n变为2,复杂度大大大降低。

如果不清楚,可以先上网搜,再看下面的程序,手动画一下(画成树):

 1 var
 2   fa:array[1..maxn]of longint //记录点i的父亲,不是祖先
 3 {high:array[1..maxn]of longint  //树的高度}
 4 function find(k:longint):longint;  //查询元素k的祖先
 5 begin
 6   if fa[x]=x then exit(x)
 7   else fa[x]=find(fa[x]);  //非常重要,将所有的点全部指向根节点(祖先),降低复杂度
 8   exit(fa[x]);
 9 end;
10 procedure unite(x,y:longint);//合并元素x,y所在的集合
11 var
12   a,b:longint;
13 begin
14   a:=find(x);
15   b:=find(y);
16   if a<>b then fa[a]:=b;
17 {if high[a]<high[b] then fa[a]:=b
18   else begin fa[b]:=a;if high[a]=high[b] then inc(rank[a]); end; }
19 end;
20 //有{}的代码可要可不要,对做题影响不大   
21    初始化时,fa[i]:=i;high[i]:=0; 

 

代码很短(去掉我加的注释),非常非常好用且漂亮的结构。 

posted on 2015-08-26 17:28  zzm1  阅读(450)  评论(0编辑  收藏  举报