数据结构=====>图

目录移到右上角啦!

一、为什么要学图

图能表示多对多的关系,这是别的数据结构所没有的

例: 线性表局限于一个直接前驱和一个直接后继的关系

树也只能有一个直接前驱也就是父节点

应用场景:

1、地图

2、集成电路图

二、图的定义和分类

定义:

图是由一组顶点和一组能够将两个顶点相连的边组成的

特殊的图:

1、自环:即一条连接一个顶点和其自身的边;

2. 平行边:连接同一对顶点的两条边; 

 图的分类:

按照连接两个顶点的边的不同,可以把图分为以下两种:

无向图:边仅仅连接两个顶点,没有其他含义;

有向图:边不仅连接两个顶点,并且具有方向;

 三、无向图

1、相关术语

相邻顶点: 当两个顶点通过一条边相连时,我们称这两个顶点是相邻的,并且称这条边依附于这两个顶点。

度: 某个顶点的度就是依附于该顶点的边的个数

子图: 是一幅图的所有边的子集(包含这些边依附的顶点)组成的图;

路径: 是由边顺序连接的一系列的顶点组成

环: 是一条至少含有一条边且终点和起点相同的路径

 连通图: 如果图中任意一个顶点都存在一条路径到达另外一个顶点,那么这幅图就称之为连通图

连通子图: 一个非连通图由若干连通的部分组成,每一个连通的部分都可以称为该图的连通子图

 2、图的存储结构

要表示一幅图,只需要表示清楚以下两部分内容即可:

1. 图中所有的顶点;

2. 所有连接顶点的边;

常见的图的存储结构有两种:邻接矩阵和邻接表 

邻接矩阵

邻接矩阵是表示图形中顶点之间相邻关系的矩阵,对于n个顶点的图而言,矩阵是的row和col表示的是1....n个点。

adj[7][8] = 1;   adj[8][7] = 1; 

 邻接表

邻接矩阵需要为每个顶点都分配n个边的空间,其实有很多边都是不存在,会造成空间的一定损失. 邻接表的实现只关心存在的边,不关心不存在的边。

因此没有空间浪费,邻接表由数组+链表组成

1.使用一个大小为V的数组 Queue[V] adj,把索引看做是顶点;

2.每个索引处adj[v]存储了一个队列,该队列中存储的是所有与该顶点相邻的其他顶点

 四、图的实现

1、图的API设计

图的API设计
类名Graph
构造方法Graph(int V):创建一个包含V个顶点但不包含边的图
成员方法1.public int V():获取图中顶点的数量 2.public int E():获取图中边的数量 3.public void addEdge(int v,int w):向图中添加一条边 v-w 4.public Queue adj(int v):获取和顶点v相邻的所有顶点
成员变量1.private final int V: 记录顶点数量 2.private int E: 记录边数量 3.private Queue[] adj: 邻接表

2、代码实现

构造图

创建顶点,边,邻接表

提供相关方法

package 基本图;

import 队列.Queue;

public class Graph {
    //顶点数目
    private final int v;
    //遍的数目
    private int E;
    //邻接表
    private Queue<Integer>[] adj;

    public Graph(int v) {
        //初始化顶点数量
        this.v = v;
        //初始化边的数量
        this.E = 0;
        //初始化邻接表
        this.adj = new Queue[v];

        for (int i = 0; i < adj.length; i++) {
            adj[i] = new Queue<>();
        }//为邻接表赋值
    }

    //获取顶点的数目
    public int v(){
        return v;
    }

    //获取边的数目
    public int E(){
        return E;
    }

    //向图中添加一条边
    public void addEdge(int v,int w){
        //在无向图中,边是没有方向的,所以该边既可以说是从v到w,也可以是w到v
        adj[v].enqueue(w) ;
        adj[w].enqueue(v) ;
        //边的数量+1
        E++;
    }

    //获取和顶点v相邻的所有顶点
    public Queue<Integer> adj(int v){
        return adj[v];
    }//返回邻接表里的值
}

导入的包

package 队列;

import java.util.Iterator;

public class Queue<T> implements Iterable<T>{
    //记录首结点
    private Node head;
    //记录最后一个结点
    private Node last;
    //记录队列中元素的个数
    private int N;


    private class Node{
        public T item;
        public Node next;

        public Node(T item, Node next) {
            this.item = item;
            this.next = next;
        }
    }
    public Queue() {
        this.head = new Node(null,null);
        this.last=null;
        this.N=0;
    }

    //判断队列是否为空
    public boolean isEmpty(){
        return N==0;
    }

    //返回队列中元素的个数
    public int size(){
        return N;
    }

    //向队列中插入元素t
    public void enqueue(T t){

        if (last==null){
            //当前尾结点last为null
            last= new Node(t,null);
            head.next=last;
        }else {
            //当前尾结点last不为null
            Node oldLast = last;
            last = new Node(t, null);
            oldLast.next=last;
        }

        //元素个数+1
        N++;
    }

    //从队列中拿出一个元素
    public T dequeue(){
        if (isEmpty()){
            return null;
        }

        Node oldFirst= head.next;
        head.next=oldFirst.next;
        N--;

        //因为出队列其实是在删除元素,因此如果队列中的元素被删除完了,需要重置last=null;

        if (isEmpty()){
            last=null;
        }
        return oldFirst.item;
    }


    @Override
    public Iterator<T> iterator() {
        return new QIterator();
    }

    private class QIterator implements Iterator{
        private Node n;

        public QIterator(){
            this.n=head;
        }
        @Override
        public boolean hasNext() {
            return n.next!=null;
        }

        @Override
        public Object next() {
            n = n.next;
            return n.item;
        }
    }


}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

名之以父

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值