数据结构之图

一、基本知识
在这里插入图片描述
二、快速入门
①创建
在这里插入图片描述

package com.ws.数据结构..创建;

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

public class Grapn {

    private ArrayList<String> dingTextList;//存储顶点集合

    private int[][] edges;//存储图对应的邻接矩阵

    private int numBian;//边的数目

    public static void main(String[] args) {
        //测试图创建
        int n=5;//节点的个数
        String v1[] = {"A","B","C","D","E"};
        //创建图
        Grapn grapn = new Grapn(n);
        //循环添加顶点
        for (String a:v1){
            grapn.insertDing(a);
        }
        //添加边
        grapn.insertBian(0,1,1);//A-B
        grapn.insertBian(0,2,1);
        grapn.insertBian(1,2,1);
        grapn.insertBian(1,3,1);
        grapn.insertBian(1,4,1);
        //显示临界就诊
        grapn.printfTu();
    }

    //构造器
    public Grapn(int n){
        //初始化矩阵和顶点集合
        edges=new int[n][n];//初始化邻接矩阵

        dingTextList=new ArrayList<>(n);//初始化顶点集合

        numBian=0;//初始化边个数
    }

    //插入节点
    public void insertDing(String ding){
        dingTextList.add(ding);
    }

    /**
     * 添加边
     * @param v1  节点下标
     * @param v2  节点下标
     * @param bian  边(二维数组值 1连)
     */
    public void insertBian(int v1,int v2,int bian){
        edges[v1][v2]=bian;
        edges[v2][v1]=bian;
        numBian++;//边数目增加
    }

    //图中常用的额方法
    //返回节点的个数
    public int getNumVer(){
        return dingTextList.size();
    }
    //返回边的个数
    public int getNumBian(){
        return numBian;
    }
    //返回节点i对应的数据
    public String getValueByIndex(int i){
        return dingTextList.get(i);
    }
    //返回v1和v2的权值
    public int getBian(int v1,int v2){
        return edges[v1][v2];
    }
    //显示图
    public void printfTu(){
        for (int[] link:edges){
            System.out.println(Arrays.toString(link));
        }
    }
}
[0, 1, 1, 0, 0]
[1, 0, 1, 1, 1]
[1, 1, 0, 0, 0]
[0, 1, 0, 0, 0]
[0, 1, 0, 0, 0]

②深度优先遍历
在这里插入图片描述

package com.ws.数据结构..遍历.深度优先DFS;

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

public class Grapn {

    private ArrayList<String> dingTextList;//存储顶点集合

    private int[][] edges;//存储图对应的邻接矩阵

    private int numBian;//边的数目
    //定义数组,标记某个节点是否被访问过
    private boolean[] ifFangWen;

    public static void main(String[] args) {
        //测试图创建
        int n=5;//节点的个数
        String v1[] = {"A","B","C","D","E"};
        //创建图
        Grapn grapn = new Grapn(n);
        //循环添加顶点
        for (String a:v1){
            grapn.insertDing(a);
        }
        //添加边
        grapn.insertBian(0,1,1);//A-B
        grapn.insertBian(0,2,1);
        grapn.insertBian(1,2,1);
        grapn.insertBian(1,3,1);
        grapn.insertBian(1,4,1);
        //显示临界就诊
        grapn.printfTu();

        //深度遍历测试
        System.out.println("深度优先遍历");
        grapn.DFS();
    }

    //构造器
    public Grapn(int n){
        //初始化矩阵和顶点集合
        edges=new int[n][n];//初始化邻接矩阵

        dingTextList=new ArrayList<>(n);//初始化顶点集合

        numBian=0;//初始化边个数

        ifFangWen=new boolean[n];//记录某个节点是否被访问
    }

    //插入节点
    public void insertDing(String ding){
        dingTextList.add(ding);
    }

    /**
     * 添加边
     * @param v1  节点下标
     * @param v2  节点下标
     * @param bian  边(二维数组值 1连)
     */
    public void insertBian(int v1,int v2,int bian){
        edges[v1][v2]=bian;
        edges[v2][v1]=bian;
        numBian++;//边数目增加
    }

    //图中常用的额方法
    //返回节点的个数
    public int getNumVer(){
        return dingTextList.size();
    }
    //返回边的个数
    public int getNumBian(){
        return numBian;
    }
    //返回节点i对应的数据
    public String getValueByIndex(int i){
        return dingTextList.get(i);
    }
    //返回v1和v2的权值
    public int getBian(int v1,int v2){
        return edges[v1][v2];
    }
    //显示图
    public void printfTu(){
        for (int[] link:edges){
            System.out.println(Arrays.toString(link));
        }
    }


    /**
     * 得到第一个临接节点的下标  开头
     * @param index  当前节点的下标
     * @return   如果存在就返回对应下标 y
     */
    public int getLinBiao(int index){
        for (int i=0;i<dingTextList.size();i++){
            if (edges[index][i]>0) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 获取下一个临接节点
     * @param x  前一个临接节点的x坐标
     * @param y               y
     * @return  下一个邻接节点的y坐标
     */
    public int getNextBiao(int x,int y){
        for (int j=y+1;j<dingTextList.size();j++){
            if(edges[x][j]>0){
                return j;
            }
        }
        return -1;
    }


    /**
     * 深度优先遍历
     * @param ifFangWen  是否访问过标志
     * @param i   第一次是0  路径节点
     */
    private void DFS(boolean[] ifFangWen,int i){
        //输出访问过的节点
        System.out.print(getValueByIndex(i)+"->");//返回相应节点的数据
        //将该节点设置为已经访问
        ifFangWen[i]=true;
        //查找i的邻接节点
        int linjie=getLinBiao(i);// A   b   c  ...
        //递归找邻接节点
        while (linjie!=-1){
            if (!ifFangWen[i]){
                //没有被访问过,就递归找访问过的 输出路径
                DFS(ifFangWen,i);
            }
            //节点已经被访问过就查找
            linjie=getNextBiao(i,linjie);//  A-B  A-C
        }
    }

    /**
     * 重载,对多个起点(多个行)进行路径查找
     */
    public void DFS(){
        //遍历所有行(节点)
        for (int i=0;i<getNumBian();i++){
            if (!ifFangWen[i]){
                DFS(ifFangWen,i);
            }
        }
    }
}
[0, 1, 1, 0, 0]
[1, 0, 1, 1, 1]
[1, 1, 0, 0, 0]
[0, 1, 0, 0, 0]
[0, 1, 0, 0, 0]
深度优先遍历
A->B->C->D->E->

③广度优先遍历
在这里插入图片描述

package com.ws.数据结构..遍历.广度优先;

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

public class Grapn {

    private ArrayList<String> dingTextList;//存储顶点集合

    private int[][] edges;//存储图对应的邻接矩阵

    private int numBian;//边的数目
    //定义数组,标记某个节点是否被访问过
    private boolean[] ifFangWen;

    public static void main(String[] args) {
        //测试图创建
        int n=5;//节点的个数
        String v1[] = {"A","B","C","D","E"};
        //创建图
        Grapn grapn = new Grapn(n);
        //循环添加顶点
        for (String a:v1){
            grapn.insertDing(a);
        }
        //添加边
        grapn.insertBian(0,1,1);//A-B
        grapn.insertBian(0,2,1);
        grapn.insertBian(1,2,1);
        grapn.insertBian(1,3,1);
        grapn.insertBian(1,4,1);
        //显示临界就诊
        grapn.printfTu();

        //深度遍历测试
        //System.out.println("深度优先遍历");
        //grapn.DFS();

        //广度优先遍历
        System.out.println();
        System.out.println("广度优先遍历");
        grapn.guangDFS();
    }

    //构造器
    public Grapn(int n){
        //初始化矩阵和顶点集合
        edges=new int[n][n];//初始化邻接矩阵

        dingTextList=new ArrayList<>(n);//初始化顶点集合

        numBian=0;//初始化边个数

        ifFangWen=new boolean[n];//记录某个节点是否被访问
    }

    //插入节点
    public void insertDing(String ding){
        dingTextList.add(ding);
    }

    /**
     * 添加边
     * @param v1  节点下标
     * @param v2  节点下标
     * @param bian  边(二维数组值 1连)
     */
    public void insertBian(int v1,int v2,int bian){
        edges[v1][v2]=bian;
        edges[v2][v1]=bian;
        numBian++;//边数目增加
    }

    //图中常用的额方法
    //返回节点的个数
    public int getNumVer(){
        return dingTextList.size();
    }
    //返回边的个数
    public int getNumBian(){
        return numBian;
    }
    //返回节点i对应的数据
    public String getValueByIndex(int i){
        return dingTextList.get(i);
    }
    //返回v1和v2的权值
    public int getBian(int v1,int v2){
        return edges[v1][v2];
    }
    //显示图
    public void printfTu(){
        for (int[] link:edges){
            System.out.println(Arrays.toString(link));
        }
    }


    /**
     * 得到第一个临接节点的下标  开头
     * @param index  当前节点的下标
     * @return   如果存在就返回对应下标 y
     */
    public int getLinBiao(int index){
        for (int i=0;i<dingTextList.size();i++){
            if (edges[index][i]>0) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 获取下一个临接节点
     * @param x  前一个临接节点的x坐标
     * @param y               y
     * @return  下一个邻接节点的y坐标
     */
    public int getNextBiao(int x,int y){
        for (int j=y+1;j<dingTextList.size();j++){
            if(edges[x][j]>0){
                return j;
            }
        }
        return -1;
    }


    /**
     * 深度优先遍历
     * @param ifFangWen  是否访问过标志
     * @param i   第一次是0  路径节点
     */
    private void DFS(boolean[] ifFangWen,int i){
        //输出访问过的节点
        System.out.print(getValueByIndex(i)+"->");//返回相应节点的数据
        //将该节点设置为已经访问
        ifFangWen[i]=true;
        //查找i的邻接节点
        int linjie=getLinBiao(i);// B  A
        //递归找邻接节点
        while (linjie!=-1){
            if (!ifFangWen[i]){
                //没有被访问过,就递归找访问过的 输出路径
                DFS(ifFangWen,i);
            }
            //节点已经被访问过就查找
            linjie=getNextBiao(i,linjie);//  A-B  A-C
        }
    }

    /**
     * 重载,对多个起点(多个行)进行路径查找
     */
    public void DFS(){
        //遍历所有行(节点)
        for (int i=0;i<getNumBian();i++){
            if (!ifFangWen[i]){
                DFS(ifFangWen,i);
            }
        }
    }

    //广度优先遍历
    private void guangDFS(boolean[] ifFangWen,int i){
        int u;//队列头节点下标  节点
        int lin;//临接节点的下标
        //队列  广度遍历节点访问顺序记录
        LinkedList<Integer> queue = new LinkedList<>();
        //访问节点
        System.out.print(getValueByIndex(i)+"->");
        //标记成已访问
        ifFangWen[i]=true;
        //将节点加入序列
        queue.addLast(i);
        while (!queue.isEmpty()){
            //取出队列的头节点下标
            u=queue.removeFirst();
            //得到第一个临接节点得到下标
            lin=getLinBiao(u);
            while (lin!=-1){
                //找到
                //是否访问过
                if (!ifFangWen[lin]){
                    //输出
                    System.out.print(getValueByIndex(lin)+"->");
                    //标记已经访问
                    ifFangWen[lin]=true;
                    //入队
                    queue.addLast(lin);
                }
                //访问过 还以当前节点,继续访问
                lin=getNextBiao(u,lin);
            }
        }
    }

    //广度优先遍历  所有的节点
    public void guangDFS(){
        for (int i=0;i<getNumBian();i++){
            if (!ifFangWen[i]){
                guangDFS(ifFangWen,i);
            }
        }
    }
}

[0, 1, 1, 0, 0]
[1, 0, 1, 1, 1]
[1, 1, 0, 0, 0]
[0, 1, 0, 0, 0]
[0, 1, 0, 0, 0]

广度优先遍历
A->B->C->D->E->

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值