图的创建和遍历

1:图的常用的数据结构

1.1:邻接矩阵

通过数组二维举证的方式来存放图的数据结构,这也是最简单原始的方法来表示图的结构。

所有的顶点数组

node1
node2
node3
node4
node5

 

 

 

 

 

以及顶点举证

  node1 node2 node3 node4 node5
node1 0 1 0 1 0
node2 1 0 0 0 0
node3 0 0 0 0 1
node4 1 0 0 0 0
node5 0 0 1 0 0

 

 

 

 

 

 

 

 

 

 

 

矩阵为1的位置,代表所在位置两个顶点的是相连的。
矩阵为0的位置,代表所在位置两个顶点的是不相连的。

这种方式直观,简单,但是当顶点较多,且边较少的时,则会有大量的存储位置的浪费!

1.2:邻接表

邻接表是通过数组和链表的方式来实现的,为所有顶点创建一个数组,然后两顶点之间如果有边相连,则在每个顶点后面链上相连的顶点即可!可以解决有邻接矩阵方式造成的大量的空白内存。

node1--> node2 --> node5
node2 --> node1 --> node3
node3 --> node2 -->node4
node4 -->node3
node5 --> node1

 

 

 

 

 

2:常用的遍历方式

2.1:depth first search

2.1.1:基于栈的搜索方式

本例子中采用stack来实现深度搜寻!因为,stack是先进后出,所以可以达到将当前搜索路径都保存进去,如果没有了可达的其他节点,则弹出当前节点,在下一个节点中重复搜索直达把所有节点都搜索完成!!!但是既然使用了stack不可避免地速度下降,

package Graph;

import java.util.Stack;

/**
 * @author :dazhu
 * @date :Created in 2020/3/13 19:04
 * @description:图的学习
 * @modified By:
 * @version: $
 */
public class Main {
    public static void main(String[] args){
        Graph g = new Graph();
        g.addVertex('A');
        g.addVertex('B');
        g.addVertex('C');
        g.addVertex('D');
        g.addVertex('E');

        g.addEdge(0,1);
        g.addEdge(1,2);
        g.addEdge(0,3);
        g.addEdge(3,4);
        g.addEdge(2,4);

        g.dfs();
    }

}

class Graph {
    private final int MAX_VERTS = 20;
    private Vertex vertexList[];
    private int adjMat[][];
    private int nVerts;
    private Stack<Integer> theStack = new Stack<Integer>();
    public Graph(){
        //初始化,顶点数组
        this.vertexList = new Vertex[MAX_VERTS];
        //创建边矩阵
        this.adjMat = new int[MAX_VERTS][MAX_VERTS];
        this.nVerts = 0;
        //初始化边矩阵
        for(int i=0;i<MAX_VERTS;i++){
            for(int j=0;j<MAX_VERTS;j++){
                adjMat[i][j] = 0;
            }
        }
    }
    //添加顶点到顶点数组
    public void addVertex(char lab){
        vertexList[nVerts++] = new Vertex(lab);
    }

    //添加边到边矩阵
    public void addEdge(int start,int end){
        adjMat[start][end] = 1;
        adjMat[end][start] = 1;
    }

    //显示所有顶点
    public void showVertexs(){
        for(int i=0;i<vertexList.length;i++){
            System.out.println(vertexList[i]);
        }
    }
    //打印指定顶点
    public void printVertex(int v){
        System.out.println(vertexList[v].label);
    }
    //depth first search,深度优先搜索(使用stack来作为辅助)
    //原来分析
    //第一步;首先取出一个顶点,以0号顶点为例子,加入stack中,
    //第二步;只要stack不为empty就一直循环,从stack得到顶点(但是不取走),
    //判断其有没有其他相连的顶点,若有则mark以下,在推入stack中。
    //第三步:重读第二步,直到stack is empty即可!
    //第四步:reset all wasVisited flag!!!
    public void dfs(){
        //begin at vertex 0
        vertexList[0].wasVisited = true;//mark it
        printVertex(0);//print it
        theStack.push(0);

        while(!theStack.isEmpty()){//until stack empty
            int v = getAdjUnvisitedVertex(theStack.peek());
            if(v==-1){//if there is no such vertex exiting
                theStack.pop();
            }
            else{//if it exits
                vertexList[v].wasVisited = true;//mark it
                printVertex(v);//print it
                theStack.push(v);//push it
            }
        }
        //stack is empty ,so we have done
        for(int i=0;i<nVerts;i++){//reset flags
            vertexList[i].wasVisited = false;
        }
    }

    //返回该列中没有标记且为1的顶点
    public int getAdjUnvisitedVertex(int v){
        for(int j=0;j<nVerts;j++){
            if(adjMat[v][j]==1&&vertexList[j].wasVisited==false){
                return j;//return first such vertex
            }
        }
        return  -1;//没有满足条件顶点,则返回-1.
    }
    //depth first search,深度优先搜索


}

//顶点类的结构
//顶点可以存在数组中,用index来表示,
//当然也可以存在链表中
class Vertex{
    public char label;//label
    public boolean wasVisited;//是否遍历过的标记。
    public Vertex(char label){
        this.label = label;
        wasVisited = false;
    }
}

2.1.2:迭代法的dfs搜索

    //用递归的方法来进行深度搜索
    //三要素:
    //当前顶点递归结束条件:当前顶点的相邻顶点都访问过。
    //递归结束情况处理:退出当前顶点的递归,回到上个顶点。
    //递归逻辑:继续向其相邻的顶点递归下去。
    public void dfs(int v){
        //在递去的过程中,显示本顶点信息。
        printVertex(v);//display it
        vertexList[v].wasVisited= true;//mark it
        //获取当前顶点的相邻顶点
        int l = getAdjUnvisitedVertex(v);
        //当前顶点没有相邻顶点,则退出本顶点的递归,回到上一个节点。
        if(l == -1){
            return ;
        }
        else{
            //如果依然存在的话,则递归下去
            dfs(l);
        }
    }

 

2.2:bearden first search

2.2.1:递归法的bfs

广度优先搜索:顾名思义相比于深度优先搜索,该方法优先搜索从出发顶点的所有相邻顶顶点,然后再搜索下一层的顶点,通过队列可以很容易实现该方法,一般通过queue的算法流程如下:

  1. 取出出发顶点如果该顶点没有标记则压入队列,并对所有相邻顶点进行遍历和访问标记,后压入队列!
  2. 当所有与相邻顶点入队列后,从尾部移除触发顶点。
  3. 取出队列,重复1-2的过程,直到队列为空,所有顶点都被标记。

借助队列的特性,先进先出可以实现广度搜索,但是也可通过迭代的方法来实现广度搜索!

迭代三要素如下:

  1. d
  2. d
  3. d
posted @ 2020-03-16 16:38  大朱123  阅读(390)  评论(0编辑  收藏  举报