图 邻接链表法

邻接链表法

基本思想:对图的每个顶点建立一个单链表,存储该顶点所有邻接顶点及其相关信息。每一个单链表设一个表头结点。

i个单链表表示依附于顶点Vi的边(对有向图是以顶点Vi为头或尾的弧)

1结点结构与邻接链表示例

链表中的结点称为表结点,每个结点由三个域组成,如图(a)所示。其中邻接点域(adjvex)指示与顶点Vi邻接的顶点在图中的位置(顶点编号),链域(nextarc)指向下一个与顶点Vi邻接的表结点,数据域(info)存储和边或弧相关的信息,如权值等。对于无权图,如果没有与边相关的其他信息,可省略此域。

每个链表设一个表头结点(称为顶点结点),由两个域组成,如图(b)所示。链域(firstarc)指向链表中的第一个结点,数据域(data) 存储顶点名或其他信息。

在图的邻接链表表示中,所有顶点结点用一个向量 以顺序结构形式存储,可以随机访问任意顶点的链表,该向量称为表头向量,向量的下标指示顶点的序号。

用邻接链表存储图时,对无向图,其邻接链表是唯一的,如图7-10所示;对有向图,其邻接链表有两种形式,如图7-11所示。

邻接表法的特点

 ◆ 表头向量中每个分量就是一个单链表的头结点,分量个数就是图中的顶点数目;

 ◆ 在边或弧稀疏的条件下,用邻接表表示比用邻接矩阵表示节省存储空间;

 ◆ 在无向图,顶点Vi的度是第i个链表的结点数;

◆ 对有向图可以建立正邻接表或逆邻接表。正邻接表是以顶点Vi为出度(即为弧的起点)而建立的邻接表;逆邻接表是以顶点Vi为入度(即为弧的终点)而建立的邻接表;

◆ 在有向图中,第i个链表中的结点数是顶点Vi的出 (或入)度;求入 (或出)度,须遍历整个邻接表;

◆ 在邻接表上容易找出任一顶点的第一个邻接点和下一个邻接点;

3  结点及其类型定义

顶点Vererex.java

[java]  view plain  copy
  1. package datastructure.graph;  
  2.   
  3. import datastructure.list.LinkList;  
  4. import datastructure.list.List;  
  5. /** 
  6.  * 图的顶点 
  7.  * @author luoweifu 
  8.  * 
  9.  */  
  10. public class Vertex{  
  11.     private Object data;  
  12.     private ArcEdge firstArc;  
  13.     /** 
  14.      * 构造函数 
  15.      */  
  16.     public Vertex() {  
  17.         data = null;  
  18.         firstArc = null;  
  19.     }  
  20.     /** 
  21.      * 构造函数 
  22.      * @param data 顶点的数据 
  23.      */  
  24.     public Vertex(Object data) {  
  25.         this.data = data;  
  26.         this.firstArc = null;  
  27.     }  
  28.     /** 
  29.      * 获得顶点的数据 
  30.      * @return 顶点的数据 
  31.      */  
  32.     public Object getData() {  
  33.         return data;  
  34.     }  
  35.     /** 
  36.      * 设置顶点的数据 
  37.      * @param data 顶点的数据 
  38.      */  
  39.     public void setData(Object data) {  
  40.         this.data = data;  
  41.     }  
  42.     /** 
  43.      * 获得第一个孤结点 
  44.      * @return 
  45.      */  
  46.     public ArcEdge getFirstArc() {  
  47.         return firstArc;  
  48.     }  
  49.     /** 
  50.      * 设置第一个孤结点 
  51.      * @param firstArc 
  52.      */  
  53.     public void setFirstArc(ArcEdge firstArc) {  
  54.         this.firstArc = firstArc;  
  55.     }  
  56.     @Override  
  57.     public boolean equals(Object obj) {  
  58.         Vertex v = (Vertex)obj;  
  59.         if(data.equals(v.getData()) )//&&  firstArc.equals(v.getFirstArc())  
  60.             return true;  
  61.         return false;  
  62.     }  
  63.     @Override  
  64.     public String toString() {  
  65.         return data + "  " + firstArc;  
  66.     }  
  67.       
  68. }  

孤结点ArcEdge.java

[java]  view plain  copy
  1. package datastructure.graph;  
  2.   
  3. /** 
  4. * 弧结点定义 
  5. * @author luoweifu 
  6. * 
  7. */  
  8. public class ArcEdge extends Edge{  
  9.     private Vertex vertex;  
  10.     private ArcEdge prior;  
  11.     private ArcEdge next;  
  12.     /** 
  13.      * 构造函数 
  14.      */  
  15.     public ArcEdge() {  
  16.         super();  
  17.     }  
  18.     /** 
  19.      * 构造函数 
  20.      * @param weight 权值 
  21.      */  
  22.     public ArcEdge(double weight) {  
  23.         super(weight);  
  24.         prior = null;  
  25.         next = null;  
  26.     }  
  27.     /** 
  28.      * 构造函数 
  29.      * @param info 边的信息 
  30.      * @param weight 权值 
  31.      */  
  32.     public ArcEdge(Object info, double weight) {  
  33.         super(info, weight);  
  34.         prior = null;  
  35.         next = null;  
  36.     }  
  37.     /** 
  38.      * 构造函数 
  39.      * @param info 边的信息 
  40.      * @param weight 权值 
  41.      * @param vertex 顶点 
  42.      */  
  43.     public ArcEdge(Object info, double weight, Vertex vertex) {  
  44.         this(info, weight);  
  45.         this.vertex = vertex;  
  46.         prior = null;  
  47.         next = null;  
  48.     }  
  49.     /** 
  50.      * 获得顶点数据 
  51.      * @return 
  52.      */  
  53.     public Vertex getVertex() {  
  54.         return vertex;  
  55.     }  
  56.     /** 
  57.      * 设置顶点 
  58.      * @param vertex 
  59.      */  
  60.     public void setVertex(Vertex vertex) {  
  61.         this.vertex = vertex;  
  62.     }  
  63.     /** 
  64.      * 获得上一个孤结点 
  65.      * @return 
  66.      */  
  67.     public ArcEdge getPrior() {  
  68.         return prior;  
  69.     }  
  70.     /** 
  71.      * 设置上一个孤结点 
  72.      * @param prior 
  73.      */  
  74.     public void setPrior(ArcEdge prior) {  
  75.         this.prior = prior;  
  76.     }  
  77.     /** 
  78.      * 获得下一个孤结点 
  79.      * @return 
  80.      */  
  81.     public ArcEdge getNext() {  
  82.         return next;  
  83.     }  
  84.     /** 
  85.      * 设置下一个孤结点 
  86.      * @param next 
  87.      */  
  88.     public void setNext(ArcEdge next) {  
  89.         this.next = next;  
  90.     }  
  91.   
  92.     @Override  
  93.     public int compareTo(Object o) {  
  94.         double w2 = ((Edge)o).getWeight();  
  95.         if(this.weight< w2)  
  96.             return -1;  
  97.         else if(this.weight > w2)  
  98.             return 1;  
  99.         return 0;  
  100.     }  
  101.       
  102.     @Override  
  103.     public boolean equals(Object obj) {  
  104.         ArcEdge arc = (ArcEdge)obj;  
  105.         if(this.next == arc.next && this.weight == arc.weight)  
  106.             return true;  
  107.         return false;  
  108.     }  
  109.   
  110.     @Override  
  111.     public Object getFirstVertex() {  
  112.         return prior.vertex.getData();  
  113.     }  
  114.   
  115.   
  116.     @Override  
  117.     public Object getSecondVertex() {  
  118.         return vertex.getData();  
  119.     }  
  120. }  

 邻接链表法表示的图ListGraph.java

[java]  view plain  copy
  1. package datastructure.graph;  
  2.   
  3. import datastructure.list.ArrayList;  
  4. import datastructure.list.List;  
  5. import datastructure.queue.ArrayQueue;  
  6. import datastructure.queue.Queue;  
  7.   
  8. public class ListGraph implements Graph {  
  9.     private List<Vertex> vertexs;  
  10.     private int edgeNum; //边的条数   
  11.     private enum Visit{unvisited, visited};  
  12.       
  13.     public ListGraph() {  
  14.         vertexs = new ArrayList();  
  15.     }  
  16.     public List getVertexs() {  
  17.         return vertexs;  
  18.     }  
  19.     public ListGraph(Object[] vexs) {  
  20.         this();  
  21.         for(int i=0; i<vexs.length; i++) {  
  22.             vertexs.add(new Vertex(vexs[i]));  
  23.         }  
  24.     }  
  25.   
  26.       
  27.     private Vertex find(Object v) {  
  28.         Vertex vex = new Vertex(v);  
  29.         int i = vertexs.indexOf(vex);  
  30.         if(i<0) {  
  31.             return null;  
  32.             //throw new ArrayIndexOutOfBoundsException("顶点" + v + "不存在!");  
  33.         }  
  34.         return (Vertex)vertexs.get(i);  
  35.     }  
  36.   
  37.   
  38.     @Override  
  39.     public void addEdge(Object v1, Object v2, double weight) {  
  40.         Vertex vex1 = find(v1);  
  41.         Vertex vex2 = find(v2);  
  42.         if(vex1 != null && vex2 != null) {  
  43.             ArcEdge e = new ArcEdge(null, weight, vex2);  
  44.             if(vex1.getFirstArc() == null) {  
  45.                 vex1.setFirstArc(e);  
  46.             } else {  
  47.                 ArcEdge arc = vex1.getFirstArc();  
  48.                 while(arc.getNext() != null) {  
  49.                     arc = arc.getNext();  
  50.                 }  
  51.                 arc.setNext(e);  
  52.                 e.setPrior(arc);  
  53.             }  
  54.             edgeNum ++;  
  55.         } else {  
  56.             throw new ArrayIndexOutOfBoundsException("顶点" + v1 + "或" + v2 + "不存在!");  
  57.         }  
  58.     }  
  59.   
  60.   
  61.     @Override  
  62.     public void addEdge(Object v1, Object v2, Object info, double weight) {  
  63.         Vertex vex1 = find(v1);  
  64.         Vertex vex2 = find(v2);  
  65.         if(vex1 != null && vex2 != null) {  
  66.             ArcEdge e = new ArcEdge(info, weight, vex2);  
  67.             if(vex1.getFirstArc() == null) {  
  68.                 vex1.setFirstArc(e);  
  69.             } else {  
  70.                 ArcEdge arc = vex1.getFirstArc();  
  71.                 while(arc.getNext() != null) {  
  72.                     arc = arc.getNext();  
  73.                 }  
  74.                 arc.setNext(e);  
  75.                 e.setPrior(arc);  
  76.             }  
  77.             edgeNum ++;  
  78.         } else {  
  79.             throw new ArrayIndexOutOfBoundsException("顶点" + v1 + "或" + v2 + "不存在!");  
  80.         }  
  81.     }  
  82.   
  83.   
  84.     @Override  
  85.     public void addVex(Object v) {  
  86.         vertexs.add(new Vertex(v));  
  87.     }  
  88.   
  89.   
  90.     @Override  
  91.     public String bfs(Object o) {  
  92.         // ----------------该方法还有点问题-------------  
  93.         Visit visit[] = new Visit[vertexs.size()];  
  94.         for(int i=0; i<vertexs.size(); i++)  
  95.             visit[i] = Visit.unvisited;  
  96.         StringBuilder sb = new StringBuilder();  
  97.         Vertex vex = new Vertex(o);//find(o);  
  98.         bfs(vex, visit, sb);  
  99.         return sb.toString();  
  100.     }  
  101.   
  102.   
  103.     private void bfs(Vertex vex, Visit[] visit, StringBuilder sb) {  
  104.         Queue queue = new ArrayQueue();  
  105.           
  106.         int n = vertexs.indexOf(vex);  
  107.         sb.append(vex.getData() + "\t");  
  108.         visit[n] = Visit.visited;  
  109.           
  110.         queue.push(vex);  
  111.         while(!queue.isEmpty()) {  
  112.             Vertex u = (Vertex) queue.deQueue();  
  113.             Vertex v = getFirstVertex(u);  
  114.             while(null != v) {  
  115.                 if(Visit.unvisited == visit[vertexs.indexOf(v)]) {  
  116.                     sb.append(v.getData() + "\t");  
  117.                     visit[vertexs.indexOf(v)] = Visit.visited;  
  118.                     queue.push(v);  
  119.                 }  
  120.                 v = getNextVertex(u, v);  
  121.             }  
  122.         }  
  123.     }  
  124.   
  125.   
  126.     @Override  
  127.     public String dfs(Object o) {  
  128.         // ----------------该方法还有点问题-------------  
  129.         Visit visit[] = new Visit[vertexs.size()];  
  130.         for(int i=0; i<vertexs.size(); i++)  
  131.             visit[i] = Visit.unvisited;  
  132.         StringBuilder sb = new StringBuilder();  
  133.         Vertex vex = new Vertex(o);//find(o);  
  134.         dfs(vex, visit, sb);  
  135.         return sb.toString();  
  136.     }  
  137.   
  138.   
  139.     private void dfs(Vertex vex, Visit[] visit, StringBuilder sb) {  
  140.         int n = vertexs.indexOf(vex);  
  141.         sb.append(vex.getData() + "\t");  
  142.         visit[n] = Visit.visited;  
  143.           
  144.         Vertex v = getFirstVertex(vex);  
  145.         while(null != v) {  
  146.             if(Visit.unvisited == visit[vertexs.indexOf(v)])  
  147.                 dfs(v, visit, sb);  
  148.             v = getNextVertex(vex, v);  
  149.         }  
  150.     }  
  151.   
  152.   
  153.     @Override  
  154.     public void clear() {  
  155.         vertexs.clear();  
  156.     }  
  157.   
  158.   
  159.     @Override  
  160.     public int getEdgeSize() {  
  161.         return edgeNum;  
  162.     }  
  163.   
  164.   
  165.     @Override  
  166.     public Object getFirstVertex(Object v) {  
  167.         Vertex vex = find(v);  
  168.         return getFirstVertex(vex).getData();  
  169.     }  
  170.       
  171.     private Vertex getFirstVertex(Vertex v) {  
  172.         if(v.getFirstArc() != null && v.getFirstArc().getVertex() != null)   
  173.             return v.getFirstArc().getVertex();  
  174.         return null;  
  175.     }  
  176.   
  177.     @Override  
  178.     public Object getNextVertex(Object v1, Object v2) {  
  179.         // ----------------该方法还有点问题-------------  
  180.         Vertex vex1 = find(v1);  
  181.         Vertex vex2 = find(v2);  
  182.         System.out.println("v1:" + v1);  
  183.         System.out.println("v2:" + v2);  
  184.         System.out.println("vex1:" + vex1);  
  185.         System.out.println("vex2:" + vex2);  
  186.         return getNextVertex(vex1, vex2);  
  187.     }  
  188.     /** 
  189.      * ----------------该方法还有点问题------------- 
  190.      * @param vex1 
  191.      * @param vex2 
  192.      * @return 
  193.      */  
  194.     private Vertex getNextVertex(Vertex vex1, Vertex vex2) {  
  195.         ArcEdge arc = vex1.getFirstArc();  
  196.         while(arc.getNext() != null && arc.getVertex()!=vex2) {  
  197.             arc = arc.getNext();  
  198.         }  
  199.         if(arc.getVertex() != null)  {  
  200.             //System.out.println(arc.getVertex());  
  201.             return arc.getNext().getVertex();  
  202.         }  
  203.         return null;  
  204.     }  
  205.   
  206.   
  207.     @Override  
  208.     public int getVertexSize() {  
  209.         return vertexs.size();  
  210.     }  
  211.   
  212.   
  213.     @Override  
  214.     public void removeEdge(Object v1, Object v2) {  
  215.         Vertex vex1 = find(v1);  
  216.         Vertex vex2 = find(v2);  
  217.         if(vex1 != null && vex2 != null) {  
  218.             ArcEdge arc = vex1.getFirstArc();  
  219.             while(arc.getNext() != null && arc.getVertex() != vex2) {  
  220.                 arc = arc.getNext();  
  221.             }  
  222.             if(arc.getVertex() == vex2) {  
  223.                 ArcEdge priEdge = arc.getPrior();  
  224.                 ArcEdge nextEdge = arc.getNext();  
  225.                 priEdge.setNext(nextEdge);  
  226.                 nextEdge.setPrior(priEdge);  
  227.                 edgeNum --;  
  228.             } else {  
  229.                 throw new ArrayIndexOutOfBoundsException("边" + v1 + "到" + v2 + "不存在!");  
  230.             }  
  231.         } else {  
  232.             throw new ArrayIndexOutOfBoundsException("顶点" + v1 + "或" + v2 + "不存在!");  
  233.         }  
  234.     }  
  235.   
  236.   
  237.     @Override  
  238.     public void removeVex(Object v) {  
  239.         for(int i=0; i<vertexs.size(); i++) {  
  240.             Vertex vex1 = (Vertex)(vertexs.get(i));  
  241.             ArcEdge arc = vex1.getFirstArc();  
  242.             if(arc  != null) {  
  243.                 while(arc.getNext() != null) {  
  244.                     if(arc.getVertex().getData() == v) {  
  245.                         removeEdge(vex1, v);  
  246.                     }  
  247.                 }  
  248.             }  
  249.         }  
  250.         Vertex vex = find(v);  
  251.         if(vex != null) {  
  252.             int i = vertexs.indexOf(vex);  
  253.             vertexs.remove(i);  
  254.         }  
  255.           
  256.     }  
  257.   
  258.     @Override  
  259.     public String printGraph() {  
  260.             StringBuilder sb = new StringBuilder();  
  261.             for(int i=0; i<vertexs.size(); i++) {  
  262.                 Vertex vex = (Vertex) vertexs.get(i);  
  263.                 sb.append("\n顶点:" + vex.getData() + "\t");  
  264.                 ArcEdge arc = vex.getFirstArc();  
  265.                 if(arc != null) {  
  266.                     sb.append("孤," + arc.getVertex().getData());  
  267.                     while(arc.getNext() != null) {  
  268.                         sb.append("\t" + arc.getNext().getVertex().getData());  
  269.                         arc = arc.getNext();  
  270.                     }  
  271.                 }  
  272.             }  
  273.         return sb.toString();  
  274.     }  
  275. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值