关闭

图(1)--图的术语和表示

72人阅读 评论(0) 收藏 举报
分类:

图的术语

线性表中的元素具有线性关系,每个元素只有一个直接前驱和一个直接后继。
树形结构中的元素之间具有明显的层次关系,每个元素只有一个前驱和若干个后继,元素之间是非线性关系。
图中元素之间具有多对多的非线性关系,图中每个元素可以有对个前驱和多个后继,任意两个元素都可以相邻,图结构比树和线性表更加复杂。

  • 是由顶点集合以及顶点间的关系集合组成的一种数据结构。顶点之间的关系称为边。一个图G记为G=(V,E),V是顶点的有限集合,E是边的有限集合。
  • 无向图中的边没有方向,每条边用两个顶点的无序对(vi,vj)表示
  • 有向图中的边有方向,每条边用两个顶点的有序对<vi,vj>表示
  • 简单图:在图中,如果不存在顶点到其自身的边,且同一条边在图中不重复出现,称为简单图。
  • 完全图:图中的边数达到最大。无向图中每两个顶点之间都存在边,有n个顶点的无向完全图中有n(n1)/2条边。有向图中,每两个顶点之间都存在方向相反的两条边,有n个顶点的有向完全图中有n(n1)条边。
  • 带权图:图中的边具有权值。在不同的应用中,权值有不同的含义。例如,如果顶点表示城市,两个顶点之间边的权值可以表示两个城市之间的距离。
  • 子图:有两个图G=(V,E)G=(V,E),如果VV,EE,则成GG的子图。
  • 邻接顶点:如果(vi,vj)是无向图中的一条边,则称vivj互为邻接顶点。如果<vi,vj>是有向图中的一条边,则称vi邻接到vj
  • 顶点的度:与顶点vi关联的边数,记为degree(vi)。度为0的点成为孤点。度为1的点成为悬挂点。在无向图中,边数是各顶点度数和的一半。在有向图中,度=入度+出度,vi的入度数以vi为终点的边数,初度是以vi为起点的边数,图中总边数等于各顶点度数和。
  • 路径:在图G=(V,E)中,如果存在顶点序列(vi,vp1,vp2,...,vpm,vj),且边(vi,vp1),(vp1,vp2),...,(vpm,vj)都是图G的边,则称顶点序列(vi,vp1,vp2,...,vpm,vj)是一条路径。对于不带权的图,路径长度是指该路径上的边数,对于带权如,路径长度值该路径上各条表的权值之和。简单路径值路径上个各顶点互不重复。回路指起点和终点相同且长度大于1的简单路径。
  • 连通性:在无向图中,如果从顶点vi到顶点vj有路径,则称两个顶点连通,如果图中任意两个顶点都是连通的,则称该图为连通图,无向图中的极大连通子图称为改图连通分量。在有向图中,如果每对顶点之间都存在两条方向相反的路径,则称该图是强连通的。有向图的极大强连通子图称为 该图的强联通分量。
  • 连通图的生成树:连通的无回路的图称为树。树中无回路且连通,如果去掉树中如意一条边,则变为森林,加上一条边则构成回路。一棵树有n个顶点,则有n-1条边。连通图的生成树是图的连通无回路子图。

图的存储结构

存储一个图包括存储图的顶点集合和边集合。通常采用顺序表存储图的顶点集合,而边集合有邻接矩阵和邻接表两种存储结构。

邻接矩阵

邻接矩阵是表示图中各顶点之间邻接关系的矩阵。根据边是否带权值,分为两种形式。

  • 不带权图的邻接矩阵:设图G=(V,E)有n个顶点,V=[v0,v1,...,vn1],E可用一个nn的矩阵描述,矩阵中元素为aij,如果(vi,vj)E<vi,vj>Eaij=1,否则aij=0。无向图的邻接矩阵是对称的。有向图的邻接矩阵不一定对称。从邻接矩阵可知顶点的度。无向图中,邻接矩阵第i行或第i列元素之和是顶点vi的度。有向图中,邻接矩阵第i行上元素之和是顶点vi的出度,第i列上元素之和是顶点vi的入度。

  • 带权图的邻接矩阵:设图G=(V,E)有n个顶点,V=[v0,v1,...,vn1],E可用一个nn的矩阵描述,矩阵中元素为aij,如果(vi,vj)E<vi,vj>E,且vivjaij=wij,如果(vi,vj)E<vi,vj>E,且vi=vjaij=0。否则aij=

    图的连接矩阵存储了任意两个顶点间的邻接关系或权值,能够实现各种操作。判断两个顶点是否邻接、获取与设置边的权值等操作时间复杂度为O(1),但是增加或删除边,不要移动大量元素,效率很低。另外在图的邻接矩阵中,如果两个点之间没有边,矩阵相应位置也存储了元素,对于稠密图,存储次效率较高,但是对于稀疏图,存储效率较低,此时需要用邻接链表。

邻接链表

图的邻接链表,采用顺序表存储顶点集合,采用链表存储和一个顶点相关的多条边的信息。每一个顶点和其邻接的边构成一个元素,存储在线性表中,这个线性表即为邻接链表。

以加权有向图为例,邻接链表是一个线性表,其中每个元素有三个域构成,顶点的序号,顶点的值,和顶点相连的边构成的链表。其中加权表有向边也包含三个域,起点的序号,终点的序号,权值。

这里写图片描述

邻接链表的实现如下:

/*
 * 加权有向图的边类
 * T:边中权值的类型
 * start:边的起点的序号
 * end:边的终点的序号
 * weight:边的权重,类型为T
 * */
public class Edge<T extends Comparable<T>> implements Comparable<Edge<T>>{
    public int start;
    public int end;
    public T weight;

    public Edge(int start,int end,T weight){
        this.start=start;
        this.end=end;
        this.weight=weight;
    }

    public String toString(){
        return "("+start+","+end+","+weight+")";
    }

    public int compareTo(Edge<T> e){
        return this.weight.compareTo(e.weight);
    }

}
/*
 * 加权有向图的顶点类
 * E:顶点数据的类型
 * T:和顶点相连的边的权值类型
 * index:顶点的序号
 * data:顶点的数据,类型为E
 * adjlink:和顶点相连的边的链表
 * */
import java.util.LinkedList;


public class Vertex<E,T extends Comparable<T>> {
    public int index;
    public E data;
    public LinkedList<Edge<T>> adjlink;

    public Vertex(int index,E data){
        this.index=index;
        this.data=data;
        this.adjlink=new LinkedList<Edge<T>>();
    }

    public Vertex(int index){
        this(index, null);
    }
}
/*
 * 加权有向图类
 * vertexlist:加权有向图的邻接链表
 * */
import java.util.LinkedList;

public class Graph <E,T extends Comparable<T>>{
    public SeqList<Vertex<E,T>> vertexlist;  //邻接链表

    //构造空图
    public Graph(int size){
        size=size<10?10:size;
        this.vertexlist=new SeqList<Vertex<E,T>>(size);
    }

    //用顶点集合和边集合构造图
    public Graph(SeqList<Vertex<E,T>> vertexs,SeqList<Edge<T>> edges){
        this(vertexs.length()*2);
        if(vertexs!=null){
            for(int i=0;i<vertexs.length();i++)
                insertVertex(vertexs.get(i));
            if(edges!=null)
                for(int j=0;j<edges.length();j++)
                    insertEdge(edges.get(j));
        }

    }

    //插入一个顶点
    public void insertVertex(Vertex<E,T> v){
        vertexlist.insert(v.index,v);
    }

    //插图一条边
    public void insertEdge(Edge<T> e){
        insertEdge(e.start,e.end,e.weight);
    }

    //根据边的起点,终点和权重插入边
    public void insertEdge(int i,int j,T weight){
        if(i>=0 && i<vertexCount() && i>=0 && i<vertexCount() && i!=j){
            Edge<T> e=new Edge<T>(i,j,weight);
            vertexlist.get(i).adjlink.add(e);
        }else
            throw new IndexOutOfBoundsException("i+"+i+",i="+j);
    }

    //计算顶点个数
    public int vertexCount(){
        return this.vertexlist.length();
    }

    //获得第i个顶点的值
    public E get(int i){
        return vertexlist.get(i).data;
    }

    //获得起点为i,终点为j的边的权重
    public T getWeight(int i,int j){
        int n=this.vertexCount();
        if(i>=0 && i<n && i>=0 && i<n){
            if(i==j)
                return null;
            LinkedList<Edge<T>> adj=this.vertexlist.get(i).adjlink;
            while(adj!=null){
                for(Edge<T> e:adj){
                    if(e.end==j)
                        return e.weight;
                }
            }
            return null;
        }
        throw new IndexOutOfBoundsException("i+"+i+",i="+j);
    }
}
/*
 * 顺序表类
 * 因为java自带的数组不能表示泛型,所以在数组的基础上创建一个数序列表类
 * */
public class SeqList <T>{
    private Object[] elem;
    private int len;

    public SeqList(int size){
        this.elem=new Object[size];
        this.len=0;
    }

    public SeqList(){
        this(64);
    }

    public boolean isEmpty(){
        return this.len==0;
    }

    public int length(){
        return this.len;
    }

    public T get(int i){
        if(i>=0 && i<this.len){
            return (T)this.elem[i];
        }
        return null;
    }

    public void set(int i,T x){
        if(x==null) 
            return;
        if(i>=0 && i<this.len)
            this.elem[i]=x;
        else
            throw new IndexOutOfBoundsException(i+"");
    }

    public void insert(int i,T x){
        if(x==null)
            return;
        if(this.len==elem.length){
            Object[] temp=this.elem;
            this.elem=new Object[temp.length*2];
            for(int j=0;j<temp.length;j++){
                this.elem[j]=temp[j];
            }
        }
        if(i>=0 && i<=this.len){
            for(int j=this.len-1;j>=i;j--){
                this.elem[j+1]=this.elem[j];
            }
            this.elem[i]=x;
            this.len++;
        }else
            throw new IndexOutOfBoundsException("i="+i);
    }
    public void append(T x){
        insert(this.len,x);
    }
}
public class Test {
    public static void main(String[] args) {

        SeqList<Vertex<String,Integer>> vertexs=new SeqList<Vertex<String,Integer>>();
        vertexs.append(new Vertex<String,Integer>(0,"A"));
        vertexs.append(new Vertex<String,Integer>(1,"B"));
        vertexs.append(new Vertex<String,Integer>(2,"C"));
        vertexs.append(new Vertex<String,Integer>(3,"D"));
        vertexs.append(new Vertex<String,Integer>(4,"E"));

        SeqList<Edge<Integer>> edges=new SeqList<Edge<Integer>>();
        edges.append(new Edge<Integer>(0,1,5));
        edges.append(new Edge<Integer>(1,0,6));
        edges.append(new Edge<Integer>(0,3,2));
        edges.append(new Edge<Integer>(1,2,7));
        edges.append(new Edge<Integer>(2,4,3));
        edges.append(new Edge<Integer>(3,2,8));
        edges.append(new Edge<Integer>(3,4,9));

        Graph<String,Integer> g=new Graph<String,Integer>(vertexs,edges);   
    }
0
0

猜你在找
C语言及程序设计(讲师:贺利坚)
Python爬虫工程师培养课程全套(讲师:韦玮)
Python全栈开发入门与实战课(讲师:李杰)
2017软考网络规划设计师视频套餐(讲师:任铄)
2017软考软件设计师视频套餐(讲师:任铄)
2017软考-信息系统项目管理师视频套餐(讲师:任铄)
软考(高级)项目经理实战营(讲师:张传波)
微信公众平台开发套餐(讲师:刘运强)
深度学习原理+实战+算法+主流框架套餐(讲师:唐宇迪)
2017系统集成项目管理工程师通关套餐(讲师:徐朋)
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:2113次
    • 积分:154
    • 等级:
    • 排名:千里之外
    • 原创:14篇
    • 转载:6篇
    • 译文:0篇
    • 评论:0条
    文章分类
    文章存档