7、创建图及图的遍历(java实现)

1、顺序表用于图的深度优先遍历

public class SeqList {

    public final int MaxSize = 10;

    public Object list[];
    public int size;

    /**
     * 初始化
     */
    public SeqList() {
        list = new Object[MaxSize];
        this.size = 0;
    }

   /* public SeqList initSeqList(SeqList seqList) {
        seqList.list = new Object[MaxSize];
        seqList.size = 0;
    }*/

    public boolean isFull(SeqList list) {
        if (list.size >= MaxSize) {
            return true;
        }
        return false;
    }

    public boolean isEmpty(SeqList list) {
        if (list.size <= 0) {
            return true;
        }
        return false;
    }

    public void insertList(SeqList seqList, int i, Object data) {
        if (isFull(seqList)) {
            System.out.println("已满无法插入");
            return;
        } else if (i < 0 || i > seqList.size) {
            System.out.println("您输入的位置有问题");
            return;
        }

        for (int j = seqList.size; j > i; j--) {
            seqList.list[j] = seqList.list[j - 1];
        }

        seqList.list[i] = data;
        seqList.size++;
    }

    public void deleteList(SeqList seqList, int i) {
        if (isEmpty(seqList)) {
            System.out.println("已空,没有元素可删除");
            return;
        } else if (i < 0 || i >= seqList.size) {
            System.out.println("您输入的位置参数有问题");
            return;
        }

        for (int j = i+1; j <= seqList.size - 1; j++) {
            seqList.list[j-1] = seqList.list[j];
        }
        seqList.size--;
    }

    public int getSize(SeqList seqList) {
        return  seqList.size;
    }

    public Object getData(SeqList seqList, int i) {
        if (isEmpty(seqList)){
            System.out.println("已空没有可取元素");
            return null;
        }else if(i<0 || i>= seqList.size){
            System.out.println("您给的位置有问题");
            return null;
        }

        return seqList.list[i];
    }

    public void printf(SeqList seqList) {
        if (isEmpty(seqList)){
            System.out.println("已空,无需遍历");
            return;
        }

        for (int i = 0; i < seqList.size; i++) {
            System.out.print(seqList.list[i] + " ");
        }
    }


    public static void main(String[] args) {
        SeqList seqList = new SeqList();

        System.out.println("元素个数: "+  seqList.getSize(seqList));
        seqList.printf(seqList);
        for (int i = 0; i < seqList.MaxSize; i++) {
            seqList.insertList(seqList,i,i);
        }

        seqList.deleteList(seqList,0);

        seqList.insertList(seqList,0,10);
        System.out.println("元素个数: "+  seqList.getSize(seqList));
        seqList.printf(seqList);


    }

}

2、创建顺序队列用户广度优先遍历

public class SeqQueue {

    public final int MaxSize = 8;

    public Object seqqueue[];
    public int front; // 队头
    public int rear;
    public int size;

    public SeqQueue() {
        this.size = 0;
        this.rear = 0;
        this.front = 0;
        this.seqqueue = new Object[MaxSize];
    }

    public boolean isFull(SeqQueue seqQueue) {
        if (seqQueue.size > 0 && seqQueue.rear == seqQueue.front) {
            return true;
        }
        return false;
    }

    public boolean isEmpty(SeqQueue seqQueue) {
        if (seqQueue.size <= 0) {
            return true;
        }
        return false;
    }

    public void queueAppend(SeqQueue seqQueue, Object data) {
        if (isFull(seqQueue)) {
            System.out.println("已满无法插入");
            return;
        }
        seqQueue.seqqueue[seqQueue.rear] = data;
        seqQueue.rear = (seqQueue.rear + 1) % MaxSize;
        seqQueue.size++;
    }

    public Object queueDelete(SeqQueue seqQueue) {
        if (isEmpty(seqQueue)) {
            System.out.println("已空");
            return null;
        }
        Object x = seqQueue.seqqueue[seqQueue.front];

        seqQueue.front = (seqQueue.front + 1) % MaxSize;
        seqQueue.size--;
        return x;
    }

    public static void main(String[] args) {
        SeqQueue seqQueue = new SeqQueue();
        seqQueue.queueDelete(seqQueue);

        for (int i = 0; i < 9; i++) {
            seqQueue.queueAppend(seqQueue, i);
        }

       for (int i = 0; i < 8; i++) {
           System.out.println( seqQueue.queueDelete(seqQueue) + " ");
           ;
        }


    }
}

3、创建需要插入的图信息类

public class CreateE {
    public int row; //行下标
    public int col; //列下标
    public  int weight; // 权重

    public CreateE() {
    }

    public CreateE(int row, int col, int weight) {
        this.row = row;
        this.col = col;
        this.weight = weight;
    }
}

4、图的实现

/**
 * 图的邻接矩阵实现
 *      —— Wij     (vi,vj)或<vi,vj>
 *      |
 * aij = —— 无穷    i != j
 *     |
 *     —— 0       i = j
 */
public class Graph {

    public final int MaxWeight = 1000; //定义为无穷大(用于存储)
    public final int MaxVertices = 10; //顶点的最大值

    SeqList vertices;  //存放顶点的顺序表
    int edge[][];      //存放边的邻接矩阵
    int numberedge;    //边的条数

    public Graph() {
        edge = new int[MaxVertices][MaxVertices]; //初始化边的最大数组(这个和顺序表差不多)
    }

    /**
     * @param graph :要初始化的图
     * @param n     :给图分配几个顶点
     */
    public Graph initGraph(Graph graph, int n) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (i == j) {
                    graph.edge[i][j] = 0; //对角线全为0
                } else {
                    graph.edge[i][j] = MaxWeight; //无穷大
                }
            }
        }

        graph.numberedge = 0;  //初始边条数0
        graph.vertices = new SeqList();  //顶点顺序表初始化

        return graph;
    }

    /**
     * 插入顶点
     *
     * @param graph  :需要插入顶点的图
     * @param vertex :插入的顶点值
     */
    public void insertVertex(Graph graph, Object vertex) {
        graph.vertices.insertList(graph.vertices, graph.vertices.size, vertex);
    }

    /**
     * 插入边
     *
     * @param graph  : 需要插入边的图
     * @param vi     :边的一个顶点
     * @param vj     :边的另一顶点
     * @param weight :边上的权重
     */
    public void insertEdge(Graph graph, int vi, int vj, int weight) {
        if (vi < 0 || vi >= graph.vertices.size || vj < 0 || vj >= graph.vertices.size) {
            System.out.println("参数vi,vj越界");
            return;
        }
        graph.edge[vi][vj] = weight;
        graph.numberedge++;
    }

    /**
     * 删除边
     * @param graph : 需要处理的图
     * @param vi :顶点i
     * @param vj : 顶点j
     */
    public void deleteEdge(Graph graph,int vi,int vj) {
        if (vi < 0 || vi >= graph.vertices.size || vj < 0 || vj >= graph.vertices.size) {
            System.out.println("参数vi,vj越界");
            return;
        }else if(graph.edge[vi][vj] == MaxWeight || vi == vj){
            System.out.println("边不存在");
            return;
        }
        graph.edge[vi][vj] = MaxWeight;
        graph.numberedge--;
    }

    /**
     * 创建图
     * @param graph :要创建的图
     * @param V :顶点
     * @param n :d顶点个数
     * @param E :边
     * @param e :边的个数
     */
    public void CreateGraph(Graph graph,Object V[],int n,CreateE E[],int e) {
        for (int i = 0; i < n; i++) {
            graph.insertVertex(graph,V[i]);
        }
        for (int i = 0; i < e; i++) {
            graph.insertEdge(graph,E[i].row,E[i].col,E[i].weight);
        }
    }

    /**
     * 获取图的边的条数
     * @param graph : 需要操作的图
     */
    public void getNumberEdge(Graph graph) {
        if (graph == null){
            System.out.println("该图不存在");
            return;
        }
        System.out.println("边的条数: " + graph.numberedge);
    }

    /**
     * 取第一个邻接顶点
     * @param graph :将要操作的图
     * @param v : 某个顶点开始的第一个邻接顶点
     * @return :找到返回邻接顶点下标,找不到反回-1,错误返回-1
     */
    public int getFirstVex(Graph graph, int v) {
        if (v < 0 || v >= graph.vertices.size) {
            System.out.println("获取第一个邻接顶点参数有问题");
            return -1;
        }
        for (int col = 0; col < graph.vertices.size; col++) {
            if (graph.edge[v][col] > 0 && graph.edge[v][col] < MaxWeight){ //找到本顶点的二位数组中大与0小于无穷的第一个值,就是第一个邻接顶点
                return col;
            }
        }
        return -1;
    }

    /**
     * 获取下一连接顶点
     * @param graph :需要操作的图
     * @param v1 :第一个顶点
     * @param v2 :第一个顶点的邻接顶点
     */
    public int getNextVex(Graph graph,int v1,int v2) {
        if (v1 <0 || v1 >= graph.vertices.size || v2 <0 || v2 >= graph.vertices.size){
            System.out.println("您要获取的下一邻接顶点参数有问题");
            return -1; 
        }
        for (int col = v2 + 1; col < graph.vertices.size; col++) {
            if (graph.edge[v1][col] >0 && graph.edge[v1][col] < MaxWeight){
                return col;
            }
        }
        return  -1;
    }

    /**
     * 连通图的深度优先遍历
     * @param graph 需要操作的图
     * @param v : 以某个顶点开始遍历
     * @param visited  :改点是否被访问
     */
    public void DepthSearch(Graph graph,int v,int visited[]) {
        System.out.print(graph.vertices.list[v] + " ");  //先打印第一个访问的顶点
        visited[v] = 1 ; //让改点为已经访问过 1 :访问过 0 : 未访问

        int col = graph.getFirstVex(graph,v);  //获取访问顶点的下一顶点

        while (col != -1){   //如果该节点存在
            if (visited[col] == 0){
                graph.DepthSearch(graph,col,visited);
            }
            col = graph.getNextVex(graph,v,col);
        }
    }

    /**
     * 非连通图的深度优先遍历
     */
    public void DepthFirstSearch(Graph graph) {
        int visited[] = new int[graph.vertices.size];
        for (int i = 0; i < graph.vertices.size; i++) {
            visited[i] = 0; //未访问标记初始值为0
        }
        for (int i = 0; i < graph.vertices.size; i++) {
            if (visited[i] == 0){
                graph.DepthSearch(graph,i,visited);
            }
        }
    }

    /**
     * 连通图的广度优先遍历
     * @param graph
     * @param v
     * @param visited
     */
    public void BroadSearch(Graph graph,int v,int visited[]) {
        SeqQueue seqQueue = new SeqQueue();
        System.out.print(graph.vertices.list[v]+" ");
        visited[v] = 1;
        seqQueue.queueAppend(seqQueue,v);   //初始顶点入队
        while (!seqQueue.isEmpty(seqQueue)){   //队列未空
            int n  = (int)seqQueue.queueDelete(seqQueue);
            int col = graph.getFirstVex(graph,n);
            while (col != -1){
                if (visited[col] == 0){
                    System.out.print(graph.vertices.list[col] + " ");
                    visited[col] = 1;    //设为已访问
                    seqQueue.queueAppend(seqQueue,col);   //邻接顶点入队
                }
                col = graph.getNextVex(graph,n,col);
            }

        }
    }

    public void BroadFirstSearch(Graph graph) {
        int visited[] = new int[graph.vertices.size];
        for (int i = 0; i < graph.vertices.size; i++) {
            visited[i] = 0; //访问标记初始为0
        }
        for (int i = 0; i < graph.vertices.size; i++) {
            if (visited[i] == 0){
                BroadSearch(graph,i,visited);
            }
        }
    }

    public static void main(String[] args) {
        Graph graph = new Graph();
        int n = 6,e=6;
        graph.initGraph(graph,n);

        Object V[] = {'A','B','C','D','E','F'};

        CreateE E[] = {new CreateE(0,1,10),new CreateE(0,4,20),new CreateE(1,3,30),new CreateE(2,1,40),new CreateE(3,2,50),new CreateE(0,5,30)};

        graph.CreateGraph(graph,V,n,E,e);

        System.out.print("顶点集合:");
        for (int i = 0; i < graph.vertices.size; i++) {
            System.out.print(graph.vertices.list[i]+ " ");
        }
        System.out.println();
        
        System.out.println("权值集合");
        for (int i = 0; i < graph.vertices.size; i++) {
            for (int j = 0; j < graph.vertices.size; j++) {
                System.out.print(graph.edge[i][j]+"\t\t");
            }
            System.out.println();
        }
        graph.getNumberEdge(graph);
        
        System.out.println("取第一个邻接顶点 : " + graph.vertices.list[graph.getFirstVex(graph,0)]); //这里取不到就会报错哦。因为取不到,我这设置返回-1
        System.out.println("取下一个邻接顶点 : " +graph.vertices.list[graph.getNextVex(graph,0,graph.getFirstVex(graph,0))]);


        
        System.out.print("图的深度优先遍历 :");

        graph.DepthFirstSearch(graph);
        System.out.println();

        System.out.print("图的广度优先遍历 :");

        graph.BroadFirstSearch(graph);
        System.out.println();
        graph.deleteEdge(graph,0,1);
        graph.getNumberEdge(graph);
        System.out.println("权值集合");
        for (int i = 0; i < graph.vertices.size; i++) {
            for (int j = 0; j < graph.vertices.size; j++) {
                System.out.print(graph.edge[i][j]+"\t\t");
            }
            System.out.println();
        }

    }


}

5、实现结果

顶点集合:A B C D E F 
权值集合
0        10        1000        1000        20        30        
1000        0        1000        30        1000        1000        
1000        40        0        1000        1000        1000        
1000        1000        50        0        1000        1000        
1000        1000        1000        1000        0        1000        
1000        1000        1000        1000        1000        0        
边的条数: 6
取第一个邻接顶点 : B
取下一个邻接顶点 : E
图的深度优先遍历 :A B D C E F 
图的广度优先遍历 :A B E F D C 
边的条数: 5
权值集合
0        1000        1000        1000        20        30        
1000        0        1000        30        1000        1000        
1000        40        0        1000        1000        1000        
1000        1000        50        0        1000        1000        
1000        1000        1000        1000        0        1000        
1000        1000        1000        1000        1000        0    

 

posted @ 2019-07-22 14:51  编程小白1024  阅读(2570)  评论(0编辑  收藏  举报