现在的位置: 首页 > 综合 > 正文

数据结构之图-图遍历(6)

2018年11月07日 ⁄ 综合 ⁄ 共 11501字 ⁄ 字号 评论关闭

1 Preface

There are many algorithm about graph, but traverse algorithm is the most important algorithm. For example, crawl all webpage from the Internet need used the traverse algorithm. There are two common algorithms to traverse a graph:
depth-first- search(DFS,深度优先算法) and breadth-first search(BFS,广度优先算法).The depth-first search is implemented with a stack(the content of the stack is the route you took from the starting vertex to get where you are), whereas the breadth-first search is implemented
with a queue
.

1.1 Aplication

 How to build a web crawler? 

To solve this problem, we should solve the following questions:

1) How to visit all webpage on the Internet?

2) How to know which webpage is visited?

Solution:

1 )If we crawl from a website, we should use BFSalgorithm, beacause we usually begin from the homepage, then crawl the adjacent page (which degien usually conside these adjacent pages is important) to the homepage.

But if we crawl all the iternet webpage, we use
priority queue with BFS
. The subsystem managed the priority queue is called scheduler(调度系统) determining which webpage to crwal after a webpage has been crawled.
After a webpage has been crawled, we parse the urls in the webpage, then put these urls in the prority queue.
2) And we should know whether a webpage is visited or not, so we use a hash table to record a webpage's url.
But there are many urls in the internet, we could not put all the urls in a hash table, because it becomes too big, how to sovle thie problem?
We can use parallel servers to solve this problems(divide big problem into small problems). When we get a url, we canhash the url to the server, then using the hash table in the server to decicde whether this url is visited.

判断图中2个结点间是否连通
思路:从结点A用深度优先算法或广度优先算法遍历图,看是否能到达结点B

2 Depth-First Search

2.1 Step

The depth-first search likes to get far away from the starting point as quickly as possible and returns only when it reaches a dead end(一条路走到黑), so the term depth means the distance from the starting point. The depth-first search
steps are:

1) push in stack(rule 1): If possible,visit an adjacent unvisited vertex,
mark it, and push it in the stack.

2) pop off stack(rule 2): If you can't follow rule1, then, if possible, pop a vertex off the stack.

3)stack is empty(rule 3): If you can't follow rule1 or rule2, you're done.

2.2 Example

Now I use the following graph describes these steps. 


1)push in stack

To carry out the depth-first search, you pick a starting point-in this case, vertex A. 

Next, push any vertex adjacent to A that hasn't yet been visited.We'll assume the vertices are selected in alphabetical order, so that bring up B. You visit B, mark it(visited), and push it on the stack.

Now you're at B, do the same thing as before: go to adjacent vertex that hasn't been visited.Then F、H pushed in stack. The push steps are like the following figure:


2) pop off stack

Now you're at H, there are no adjacent vertices adjacent to H.Then following rule 2, you pop H off the stack, which bring you back to F. Now do the same thing as before: rule1, then rule2: the vertex has no unvisited adjacent
vertices, pop it. So F、B are popped off the stack. 


3) push in stack and pop off stack

Now you're at A, there are adjacent vertices to A. Then do the same thing following rule1 and rule2. So D、G、I are pushed in stack, then I、G、D are popped off the stack. Now you are at A, has no unvisited vertices, so pop A off
the stack.


4) stack is empty

Now there is nothing left in stack, which brings up rule3: stack is empty.

We can get the order in which you visit the vertices from the content of the stack:ABFHDGI

2.3 Java Implement

// dfs.java
// demonstrates depth-first search
// to run this program: C>java DFSApp
////////////////////////////////////////////////////////////////
class StackX
   {
   private final int SIZE = 20;
   private int[] st;
   private int top;
// ------------------------------------------------------------
   public StackX()           // constructor
      {
      st = new int[SIZE];    // make array
      top = -1;
      }
// ------------------------------------------------------------
   public void push(int j)   // put item on stack
      { st[++top] = j; }
// ------------------------------------------------------------
   public int pop()          // take item off stack
      { return st[top--]; }
// ------------------------------------------------------------
   public int peek()         // peek at top of stack
      { return st[top]; }
// ------------------------------------------------------------
   public boolean isEmpty()  // true if nothing on stack
      { return (top == -1); }
// ------------------------------------------------------------
   }  // end class StackX
////////////////////////////////////////////////////////////////
class Vertex
   {
   public char label;        // label (e.g. 'A')
   public boolean wasVisited;
// ------------------------------------------------------------
   public Vertex(char lab)   // constructor
      {
      label = lab;
      wasVisited = false;
      }
// ------------------------------------------------------------
   }  // end class Vertex
////////////////////////////////////////////////////////////////
class Graph
   {
   private final int MAX_VERTS = 20;
   private Vertex vertexList[]; // list of vertices
   private int adjMat[][];      // adjacency matrix
   private int nVerts;          // current number of vertices
   private StackX theStack;
// ------------------------------------------------------------
   public Graph()               // constructor
      {
      vertexList = new Vertex[MAX_VERTS];
                                          // adjacency matrix
      adjMat = new int[MAX_VERTS][MAX_VERTS];
      nVerts = 0;
      for(int y=0; y<MAX_VERTS; y++)      // set adjacency
         for(int x=0; x<MAX_VERTS; x++)   //    matrix to 0
            adjMat[x][y] = 0;
      theStack = new StackX();
      }  // end constructor
// ------------------------------------------------------------
   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 displayVertex(int v)
      {
      System.out.print(vertexList[v].label);
      }
// ------------------------------------------------------------
   public void dfs()  // depth-first search
      {                                 // begin at vertex 0
      vertexList[0].wasVisited = true;  // mark it
      displayVertex(0);                 // display it
      theStack.push(0);                 // push it

      while( !theStack.isEmpty() )      // until stack empty,
         {
         // get an unvisited vertex adjacent to stack top
         int v = getAdjUnvisitedVertex( theStack.peek() );
         if(v == -1)                    // if no such vertex,
            theStack.pop();
         else                           // if it exists,
            {
            vertexList[v].wasVisited = true;  // mark it
            displayVertex(v);                 // display it
            theStack.push(v);                 // push it
            }
         }  // end while

      // stack is empty, so we're done
      for(int j=0; j<nVerts; j++)          // reset flags
         vertexList[j].wasVisited = false;
      }  // end dfs
// ------------------------------------------------------------
   // returns an unvisited vertex adj to v
   public int getAdjUnvisitedVertex(int v)
      {
      for(int j=0; j<nVerts; j++)
         if(adjMat[v][j]==1 && vertexList[j].wasVisited==false)
            return j;
      return -1;
      }  // end getAdjUnvisitedVertex()
// ------------------------------------------------------------
   }  // end class Graph
////////////////////////////////////////////////////////////////
class DFSApp
   {
   public static void main(String[] args)
      {
      Graph theGraph = new Graph();
      theGraph.addVertex('A');    // 0  (start for dfs)
      theGraph.addVertex('B');    // 1
      theGraph.addVertex('C');    // 2
      theGraph.addVertex('D');    // 3
      theGraph.addVertex('E');    // 4

      theGraph.addEdge(0, 1);     // AB
      theGraph.addEdge(1, 2);     // BC
      theGraph.addEdge(0, 3);     // AD
      theGraph.addEdge(3, 4);     // DE

      System.out.print("Visits: ");
      theGraph.dfs();             // depth-first search
      System.out.println();
      }  // end main()
   }  // end class DFSApp
////////////////////////////////////////////////////////////////

3 Breadth-First Search

In the breadth-first search, on the other hand, the algorithm likes to stay as close as possible to the starting point(尽可能的访问每个节点所有直接连接的其他节点). It visits all the vertices adjacent to the starting vertex, and only then goes further afield.
This kind of search is implemented using a queue.

The breadth-first search steps are:

1)insert in queue(rule 1): visit the next unvisited (if there is one) that's adjacent to the current vertex, mark
it, and insert it into the queue.

2)remove from queue(rule 2): if you can't carry out rule1 because there are no more unvisited vertices, remove a vertex from the queue(if possible) and make it the current vertex.

3) queue is empty(rule 3): if you can't carry out rule2 because the queue is empty, you're done.

3.2 Example

Using the following graph describes these steps:


A is the current vertex, s you visit  it and make it the current vertex. Then visit A's adjacent vertices, mark it ,and insert it into the queue, so insert B,C,D,E are inserted in the queue.

Now A has no more unvisited vertices, then remove vertex B from  queue. So now B is the current vertex. Do these steps until queue is empty,then end .



The content of the queue is the route you took from the starting point to the current vertex. The nodes are visited in the order ABCDEFGHI.

3.3 Java Implement

// bfs.java
// demonstrates breadth-first search
// to run this program: C>java BFSApp
////////////////////////////////////////////////////////////////
class Queue
   {
   private final int SIZE = 20;
   private int[] queArray;
   private int front;
   private int rear;
// -------------------------------------------------------------
   public Queue()            // constructor
      {
      queArray = new int[SIZE];
      front = 0;
      rear = -1;
      }
// -------------------------------------------------------------
   public void insert(int j) // put item at rear of queue
      {
      if(rear == SIZE-1)
         rear = -1;
      queArray[++rear] = j;
      }
// -------------------------------------------------------------
   public int remove()       // take item from front of queue
      {
      int temp = queArray[front++];
      if(front == SIZE)
         front = 0;
      return temp;
      }
// -------------------------------------------------------------
   public boolean isEmpty()  // true if queue is empty
      {
      return ( rear+1==front || (front+SIZE-1==rear) );
      }
// -------------------------------------------------------------
   }  // end class Queue
////////////////////////////////////////////////////////////////
class Vertex
   {
   public char label;        // label (e.g. 'A')
   public boolean wasVisited;
// -------------------------------------------------------------
   public Vertex(char lab)   // constructor
      {
      label = lab;
      wasVisited = false;
      }
// -------------------------------------------------------------
   }  // end class Vertex
////////////////////////////////////////////////////////////////
class Graph
   {
   private final int MAX_VERTS = 20;
   private Vertex vertexList[]; // list of vertices
   private int adjMat[][];      // adjacency matrix
   private int nVerts;          // current number of vertices
   private Queue theQueue;
// ------------------------------------------------------------
   public Graph()               // constructor
      {
      vertexList = new Vertex[MAX_VERTS];
                                          // adjacency matrix
      adjMat = new int[MAX_VERTS][MAX_VERTS];
      nVerts = 0;
      for(int j=0; j<MAX_VERTS; j++)      // set adjacency
         for(int k=0; k<MAX_VERTS; k++)   //    matrix to 0
            adjMat[j][k] = 0;
      theQueue = new Queue();
      }  // end constructor
// -------------------------------------------------------------
   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 displayVertex(int v)
      {
      System.out.print(vertexList[v].label);
      }
// -------------------------------------------------------------
   public void bfs()                   // breadth-first search
      {                                // begin at vertex 0
      vertexList[0].wasVisited = true; // mark it
      displayVertex(0);                // display it
      theQueue.insert(0);              // insert at tail
      int v2;

      while( !theQueue.isEmpty() )     // until queue empty,
         {
         int v1 = theQueue.remove();   // remove vertex at head
         // until it has no unvisited neighbors
         while( (v2=getAdjUnvisitedVertex(v1)) != -1 )
            {                                  // get one,
            vertexList[v2].wasVisited = true;  // mark it
            displayVertex(v2);                 // display it
            theQueue.insert(v2);               // insert it
            }   // end while
         }  // end while(queue not empty)

      // queue is empty, so we're done
      for(int j=0; j<nVerts; j++)             // reset flags
         vertexList[j].wasVisited = false;
      }  // end bfs()
// -------------------------------------------------------------
   // returns an unvisited vertex adj to v
   public int getAdjUnvisitedVertex(int v)
      {
      for(int j=0; j<nVerts; j++)
         if(adjMat[v][j]==1 && vertexList[j].wasVisited==false)
            return j;
      return -1;
      }  // end getAdjUnvisitedVertex()
// -------------------------------------------------------------
   }  // end class Graph
////////////////////////////////////////////////////////////////
class BFSApp
   {
   public static void main(String[] args)
      {
      Graph theGraph = new Graph();
      theGraph.addVertex('A');    // 0  (start for bfs)
      theGraph.addVertex('B');    // 1
      theGraph.addVertex('C');    // 2
      theGraph.addVertex('D');    // 3
      theGraph.addVertex('E');    // 4

      theGraph.addEdge(0, 1);     // AB
      theGraph.addEdge(1, 2);     // BC
      theGraph.addEdge(0, 3);     // AD
      theGraph.addEdge(3, 4);     // DE

      System.out.print("Visits: ");
      theGraph.bfs();             // breadth-first search
      System.out.println();
      }  // end main()
   }  // end class BFSApp
////////////////////////////////////////////////////////////////


抱歉!评论已关闭.