zoukankan      html  css  js  c++  java
  • 图(一)

    图(Graph)

    图(graph)是一种比线性表、树更为复杂的数据结构。在线性表中,数据元素之间呈线性关系,即每个元素只有一个直接前驱和一个直接后继。在树型结构中,数据元素之间有明显的的层次关系,即每个结点只有一个直接前驱,但可有多个直接后继,而在图结构中,每个结点即可有多个直接前驱,也可有多个直接后继,因此,树结构是图结构的一种特殊情形。当一个树结构中允许同一结点出现在不同分支上时,该树结构实际上就是一个图结构。

    邻接:如果两个顶点被同一条边连接,就称这两个顶点是邻接的。

    路径:边的序列。

    连通图:至少有一条路径可以连接器所有的顶点,这个图就称为连通图。

    有向图:如果边是没有方向的,称为无向图,反之为有向图。

    带权图:在某些图,边被赋予一种权值,权值是一个数字,它代表两个顶点的物理距离,或时间或花费,这种图称为带权图。


    图的存储结构

    1)邻接矩阵

    邻接矩阵是一个二维数组,数据项表示两点间是否存在边,如果图有 N 个顶点,则邻接矩阵就是 N*N 的数组。两个顶点间有边的表示为1,没有边则为0。也可以用 boolean 表示。

           A     B     C     D
       A      0     1     1     1
       B      1     0     0     1
       C      1     0     0     0
       D      1     1     0     0
                                 如图: 
     
    2)邻接表
       顶点   包含邻接顶点的链表
        A   B -> C -> D
        B   A -> D
        C   A
        D   A -> B

    在邻接表中,符号 -> 表示链表中的一个节点,每个节点都是一个顶点。邻接表仅表示了当前顶点与哪些顶点连接,与顶点顺序无关。

    顶点代码:

    public class Vertex {
    
        private char label;
    
        private boolean isVisited;
    
        public Vertex(char label) {
            this.label = label;
        }
    
        public char getLabel() {
            return label;
        }
    
        public boolean isVisited() {
            return isVisited;
        }
    
        public void setVisited(boolean isVisited) {
            this.isVisited = isVisited;
        }
    
    }

    图的代码:

    public class Graph0 {
    
        private final int MAX_VERTS = 20;
    
        private Vertex[] vertexArray;
    
        private int[][] adjMat;
    
        private int nVerts;
    
        public Graph0() {
            vertexArray = new Vertex[MAX_VERTS];
            adjMat = new int[MAX_VERTS][MAX_VERTS];
            nVerts = 0;
        }
    
        public void addVertex(char label) {
            vertexArray[nVerts++] = new Vertex(label);
        }
    
        public void addEdge(int start, int end) {
            adjMat[start][end] = 1;
            adjMat[end][start] = 1;
        }
    
    }

       图x

    图的遍历

    1)深度优先遍历

    深度优先要得到距离起始点最远的顶点,然后再不能继续前进的时候返回。栈的内容是从起始点到各个顶点访问的整个过程。

    规则:

    1. 如果可能,访问一个邻接的未访问顶点,标记它,放入栈中。
    2. 当不能执行规则1,如果栈不空,则从栈中弹出一个顶点。
    3. 如果不能执行规则1、规则2,就完成了整个遍历过程。
    public class StackX {
    
        private final int SIZE;
    
        private int[] array;
    
        private int top;
    
        public StackX(int size) {
            this.SIZE = size;
            array = new int[SIZE];
            top = -1;
        }
    
        public void push(int i) {
            array[++top] = i;
        }
    
        public int pop() {
            return array[top--];
        }
    
        public int peek() {
            return array[top];
        }
    
        public boolean isEmpty() {
            return top == -1;
        }
    
    }
    public class Graph {
    
        private final int MAX_VERTS;
    
        private Vertex[] vertexArray;
    
        private int[][] adjMat;
    
        private StackX stack;
    
        private int nVerts;
    
        public Graph(int verts) {
            this.MAX_VERTS = verts;
            vertexArray = new Vertex[MAX_VERTS];
            adjMat = new int[MAX_VERTS][MAX_VERTS];
            stack = new StackX(MAX_VERTS);
            nVerts = 0;
        }
    
        public void addVertex(char label) {
            vertexArray[nVerts++] = new Vertex(label);
        }
    
        public void addEdge(int start, int end) {
            adjMat[start][end] = 1;
            adjMat[end][start] = 1;
        }
    
        public void displayVertex(int index) {
            System.out.print(vertexArray[index].getLabel() + " -> ");
        }
    
        //depth first search
        public void dfs() {
            vertexArray[0].setVisited(true);
            displayVertex(0);
            stack.push(0);
    
            while (!stack.isEmpty()) {
                int v = getAdjUnvisitedVertex(stack.peek());
                if (v == -1) {
                    stack.pop();
                }
                else {
                    vertexArray[v].setVisited(true);
                    displayVertex(v);
                    stack.push(v);
                }
            }
    
            for (int j = 0; j < MAX_VERTS; j++) {
                if (vertexArray[j] != null) {
                    vertexArray[j].setVisited(false);
                }
            }
        }
    
        public int getAdjUnvisitedVertex(int v) {
            for (int k = 0; k < nVerts; k++) {
                if (adjMat[v][k] == 1 && vertexArray[k].isVisited() == false) {
                    return k;
                }
            }
            return -1;
        }
    
    }

    在图x中,遍历的顺序为:A -> B -> E -> F -> C -> D -> G -> H -> I 


    2)广度优先遍历

    与深度优先相反,它首先访问起始顶点的所有邻接点,再一层一层地访问其它较远的顶点。

    寻求两个顶点之间最短距离,可以使用广度优先遍历。

    规则:

    1. 访问下一个未来访问的邻接点(如果存在),这个顶点必须当前顶点的邻接点,标记它,并把它插入队列中。
    2. 如果因为已经没有未访问的顶点而不能执行规则1,那么从队列头取一个顶点(如果存在),并使其成为当前顶点。
    3. 如果因为队列为空而不能执行规则2,则遍历结束。
    public class Queue {
    
        private final int SIZE;
    
        private int[] queArray;
    
        private int front;
    
        private int rear;
    
        public Queue(int size) {
            this.SIZE = size;
            queArray = new int[SIZE];
            front = 0;
            rear = -1;
        }
    
        public void insert(int d) {
            if (rear == SIZE - 1) {
                rear = -1;
            }
            queArray[++rear] = d;
        }
    
        public int remove() {
            int temp = queArray[front++];
            if (front == SIZE) {
                front = 0;
            }
            return temp;
        }
    
        public boolean isEmpty() {
            return (rear + 1 == front) || (front + SIZE - 1 == rear);
        }
    
    }
    public class Graph2 {
    
        private final int MAX_VERTS;
    
        private Vertex[] vertexArray;
    
        private int[][] adjMat;
    
        private Queue queue;
    
        private int nVerts;
    
        public Graph2(int verts) {
            this.MAX_VERTS = verts;
            vertexArray = new Vertex[MAX_VERTS];
            adjMat = new int[MAX_VERTS][MAX_VERTS];
            queue = new Queue(MAX_VERTS);
            nVerts = 0;
        }
    
        public void addVertex(char label) {
            vertexArray[nVerts++] = new Vertex(label);
        }
    
        public void addEdge(int start, int end) {
            adjMat[start][end] = 1;
            adjMat[end][start] = 1;
        }
    
        public void displayVertex(int index) {
            System.out.print(vertexArray[index].getLabel() + " -> ");
        }
    
        public int getAdjUnvisitedVertex(int v) {
            for (int k = 0; k < nVerts; k++) {
                if (adjMat[v][k] == 1 && vertexArray[k].isVisited() == false) {
                    return k;
                }
            }
            return -1;
        }
    
        //breadth first search
        public void bfs() {
            vertexArray[0].setVisited(true);
            displayVertex(0);
            queue.insert(0);
    
            while (!queue.isEmpty()) {
                int r = queue.remove();
                int v;
                while ((v = getAdjUnvisitedVertex(r)) != -1) {
                    vertexArray[v].setVisited(true);
                    displayVertex(v);
                    queue.insert(v);
                }
    
            }
    
            for (int j = 0; j < MAX_VERTS; j++) {
                if (vertexArray[j] != null) {
                    vertexArray[j].setVisited(false);
                }
            }
        }
        
    }

    在图x中,遍历的顺序为:A -> B -> C -> D -> E -> F -> G -> H -> I 

  • 相关阅读:
    10个你可能不知道的JavaScript小技巧
    JS实现rgb与16进制颜色相互转换
    JavaScript 计算两个颜色叠加值
    软件测试定义和目的(1)
    服务器查看系统日记
    SQL Server 2012 安装成功后找不到SQL server Management
    windowns 10 安装 win64_11gR2_database
    C#获得当前目录和执行目录及执行文件的路径
    卸载yaml,重新安装的坑
    IIS的卸载和安装
  • 原文地址:https://www.cnblogs.com/xuekyo/p/2913420.html
Copyright © 2011-2022 走看看