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    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM