数据结构与算法(十)(图)

1.基本概念介绍:
图:需要表示多对多的关系时,使用图
图中的重要概念:顶点(节点),边,路径,无向图,有向图,带权图(网)
2.图的表示方式:
二维数组(邻接矩阵)
在这里插入图片描述
链表(与数组结合)(邻接表)
在这里插入图片描述
3.图的创建与深度优先算法分析
图的创建:使用邻接矩阵的方式创建图
深度优先算法:
a.访问初始节点A,并将A节点标记为已访问
b.查找节点A的第一个邻接节点B
c.此时存在两种情况,B存在,继续执行下一步,B不存在,证明A不存在邻接节点,返回第一步重新选择初始节点
d.此时B存在,此时又存在两种情况B没有被访问过,此时将B当成A,递归重复进行上述步骤,寻找节点A的下一个邻接节点,B被访问过,直接需要寻找节点A的下一个邻接节点
4.代码实现

package graph;

import java.util.ArrayList;
import java.util.Arrays;

public class Graph {
    private ArrayList<String> vertexList;//节点集合
    private int[][] edges;//表示边的邻接矩阵
    private int numOfEdges;//表示边的数量
    private boolean[] isVistied;//判断是否被访问

    public static void main(String[] args) {
        String[] strings = {"A","B","C","D","E"};
        Graph graph = new Graph(strings.length);
        for(int i=0;i<strings.length;i++){
            graph.addVertex(strings[i]);
        }
        graph.addEdge(0,1,1);
        graph.addEdge(0,2,1);
        graph.addEdge(1,2,1);
        graph.addEdge(1,3,1);
        graph.addEdge(1,4,1);
        graph.showEdges();
        graph.dfs();
    }

    //得到当前节点的第一个邻接节点的下标
    public int getFirstNeighbor(int index){
        for(int i=0;i<vertexList.size();i++){
            if(edges[index][i]>0){
                return i;
            }
        }
        return -1;
    }

    //如果当前节点的邻接节点被访问过,此时需要寻找当前节点的下一个邻接节点
    public int getNextNerghbor(int thisIndex,int nextIndex){
        for(int j=nextIndex+1;j<vertexList.size();j++){
            if(edges[thisIndex][j]>0){
                return j;
            }
        }
        return -1;
    }

    //深度优先算法
    public void dfs(boolean[] isVistied,int index){
        System.out.println(vertexList.get(index));
        isVistied[index] = true;
        int w = getFirstNeighbor(index);
        while(w!=-1){
            if(!isVistied[w]){
                dfs(isVistied,w);
            }
            w = getNextNerghbor(index,w);
        }
    }

    public void dfs(){
        for(int i=0;i<vertexList.size();i++){
            if(!isVistied[i]){
                dfs(isVistied,i);
            }
        }
    }

    //构造器
    public Graph(int n){
        vertexList = new ArrayList<>(n);
        edges = new int[n][n];
        isVistied = new boolean[n];
        numOfEdges = 0;
    }

    //增加节点
    public void addVertex(String vertex){
        vertexList.add(vertex);
    }

    //增加边
    public void addEdge(int v1,int v2,int weight){
        edges[v1][v2] = weight;
        edges[v2][v1] = weight;
        numOfEdges ++;
    }

    //返回节点个数
    public int getNumOfVertex(){
        return vertexList.size();
    }

    //返回边的数量
    public int getNumOfEdges(){
        return numOfEdges;
    }

    //返回节点i对应的数据
    public String getValueByIndex(int i){
        return vertexList.get(i);
    }

    //返回v1,v2的权值
    public int getWeight(int v1,int v2){
        return edges[v1][v2];
    }

    //遍历edges
    public void showEdges(){
        for(int[] edge:edges){
            System.out.println(Arrays.toString(edge));
        }
    }
}

5.图的广度优先算法思路分析
a.访问初始节点A,并将A标记为已访问
b.将节点A放入队列
c.此时判断队列是否为空,不为空继续执行,为空方法结束
d.拿出队列的第一项u
e.查找u的第一个邻接节点w
f.此时分为两种情况,w不存在,回到步骤c,w存在,此时又分为两种情况
g.w存在,也分为两种情况,w被访问,查找u的下一个邻接节点,w未被访问,访问w,并将w记录为被访问状态,将w放入队列,查找u的下一个邻接节点
6.代码实现

//广度有点算法
    public void bfs(boolean[] isVistied,int index){
        LinkedList<Integer> queue = new LinkedList<>();
        int u;//队列中的第一个
        int w;//当前节点的第一个邻接节点
        System.out.println(vertexList.get(index));
        isVistied[index] = true;
        queue.addLast(index);
        while(!queue.isEmpty()){
            u = queue.removeFirst();
            w = getFirstNeighbor(u);
            while(w != -1){
                if(!isVistied[w]){
                    System.out.println(vertexList.get(w));
                    isVistied[w] = true;
                    queue.addLast(w);
                }
                w = getNextNerghbor(u,w);
            }
        }
    }
    public void bfs(){
        for(int i=0;i<vertexList.size();i++){
            if(!isVistied[i]){
                bfs(isVistied,i);
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值