Author: July January 1, 2011
---------------------------------
My reference: Introduction to Algorithms
My statement: Personal Original, reprinted please indicate the source.
OK.
There are many articles on such BFS and DFS algorithms on the Internet. However, there is no such reason.
After reading this article, I think,
You will have a thorough understanding of the breadth-first search and depth-first search of graphs.
---------------------
We started with BFS:
First, let's take a look at the overview of this BFS breadth-first search algorithm in the introduction to algorithms.
Introduction to algorithms, second edition, Chinese translation, 324th pages.
Breadth-first search (BFS)
The Prime Minimum Spanning Tree Algorithm and Dijkstra single-source shortest path algorithm both adopt the same idea as the BFS algorithm.
// U for v's ancestors or parents.
BFS (G, s)
1 for each vertex uε V [G]-{s}
2 do color [u] ← WHITE
3 d [u] ← ∞
4 π [u] ← NIL
// Except for the Source Vertex s, line 1-4 sets each vertex to white and d [u] of each vertex u to infinity,
// Set the parent of each vertex to NIL.
5 color [s] gradient GRAY
// Set Source Vertex s to gray in Row 3, because the Source Vertex has been found at the beginning of the process.
6 d [s] defaults 0 // initialize d [s] to 0.
7 π [s] ← NIL // set the parent vertex of the Source Vertex to NIL.
8. Q: Why?
9 ENQUEUE (Q, s) // enter the queue
// Lines 8th and 9 initialize the queue Q so that it only contains the Source Vertex s.
10 while Q =ø
11 do u shortdequeue (Q) // leaves the queue
// Row 3: Determine the gray vertex u in the Q header of the queue header and remove it from Q.
12 for each v ε Adj [u] // for loop test each vertex v in the u's adjacent table
13 do if color [v] = WHITE
14 then color [v] GRAY // set it to GRAY
15 d [v] ← d [u] + 1 // The distance is set to d [u] + 1
16 π [v] ← u // u is the parent of the vertex.
17 ENQUEUE (Q, v) // insert to queue
18 color [u] BLACK // u is set to BLACK
The demonstration process of the "by" and "Link" is clear and easy to understand:
Traverse the demo address with breadth first:
Http://sjjg.js.zwu.edu.cn/SFXX/sf1/gdyxbl.html
Bytes -----------------------------------------------------------------------------------------------------------------
OK. Next, we will explain the deep Priority Search Algorithm in detail.
Deep prioritization algorithm DFS
// U for V's ancestors or parents.
DFS (g)
1 for each vertex uε V [g]
2 do color [u] ← white
3 π [u] ← Nil
// In line 1-3, all vertices are set to white, and all π fields are initialized to nil.
4 time counter 0 // reset time counter
5 for each vertex uε V [g]
6 do if color [u] = white
7 then DFS-VISIT (u) // call the DFS-VISIT to access u, u becomes a new tree in the depth-first Forest
// Line 5-7, search the vertices in V in sequence, and call the DFS-VISIT to access the vertices when the white vertices are found.
// Each vertex u corresponds to a time point d [u] and a time point f [u].
DFS-VISIT)
1 color [u] starting with GRAY // u is found and set to white
2 time elapsed time + 1 // time Increments
3 d [u] <-time // record the time when u was found
4 for each v ε Adj [u] // check and access each adjacent point v of u
5 do if color [v] = WHITE // if v is WHITE, recursively access v.
6 then π [v] ← u // set u to v's ancestors
7 DFS-VISIT (v) // recursive depth, access neighbor node v
8 color [u] <-BLACK // u is set to BLACK, indicating that both the u and Its Adjacent contacts have been accessed.
9 f [u] processing time + 1 // The access completion time is recorded in f [u.
// Complete
Line 1-3, line 5-7 occupies the cycle time of O (V), which does not include the time when the DFS-VISIT was called.
For each vertex v (-V, the process DFS-VISIT is called in sequence only, because this process is called only for white vertices.
Line 4-7: the execution time is O (E ).
Therefore, the total execution time is O (V + E ).
The following link provides a demo system for deep Priority Search:
Figure depth-first traversal Demonstration System:
Http://sjjg.js.zwu.edu.cn/SFXX/sf1/sdyxbl.html
====================
Finally, let's look at the Recursive Implementation and non-Recursive Implementation of deep priority search.
1. Implement DFS recursion:
Void dftR (PGraphMatrix inGraph)
{
PVexType v;
AssertF (inGraph! = NULL, "in dftR, pass in inGraph is null/n ");
Printf ("/n = start of dft recursive version =/n ");
For (v = firstVertex (inGraph); v! = NULL; v = nextVertex (inGraph, v ))
If (v-> marked = 0)
DfsR (inGraph, v );
Printf ("/n = end of dft recursive version =/n ");
}
Void dfsR (PGraphMatrix inGraph, PVexType inV)
{
PVexType v1;
AssertF (inGraph! = NULL, "in dfsR, inGraph is null/n ");
AssertF (inV! = NULL, "in dfsR, inV is null/n ");
InV-> marked = 1;
Visit (inV );
For (v1 = firstAdjacent (inGraph, inV); v1! = NULL; v1 = nextAdjacent (inGraph, inV, v1 ))
// When v1 is the adjacent contact of v.
If (v1-> marked = 0)
DfsR (inGraph, v1 );
}
2. DFS non-Recursive Implementation
Non-recursive version-stack implementation based on the node type queue
Non-Recursive Implementation of the forward traversal of the contact tree:
We can see that it is simply divided into two parts: "exploring the left" and "visiting the right". The nodes popped up in the stack need to be used to access the right.
In the depth-first search of a graph, it can also be divided into two parts: "Deep Exploration" and "returning to the top-layer unvisited node:
1. The process of in-depth graph exploration is exactly the same as that of the tree's "left,
You only need to make a decision on the accessed node.
2. The "Access Right" in the back-to-back visit node of the graph is the same as that in the pre-sequential traversal of the tree.
However, for a tree, operations such as rightSibling are provided, so the right access is quite good.
To implement the corresponding functions, consider m unaccessed nodes in the lower-Layer Nodes of each current node,
Then, the leftmost node needs to be accessed, and M-1 nodes are pushed to a queue in the order from left to right.
And press the queue into a stack.
In this way, when the adjacent contacts of the current node have been accessed or no adjacent contacts need to be returned,
Then, the queue elements are popped up from the queue node at the top of the stack, and the node elements in the queue are queued in sequence,
If the queue has been accessed, it will continue to go out (when the current queue node is empty, it will continue to go out of the stack, and the queue at the top of the next stack will pop up ),
Until there is an unaccessed node (the access point is set to the current point) or until the stack is empty (the current deep-Priority Search Tree stops searching ).
The method to describe the algorithm through a simplified C source program is as follows:
// Dfsur: function from a node inv of a tree, access all adjacent nodes with depth first
Void dfsur (pgraphmatrix ingraph, pvextype INV)
{
Psinglerearseqqueue tmpq; // defines a temporary queue to accept the top-stack queue and use it when pushing the stack.
Pseqstack teststack; // M-1 unaccessed node in the current layer to form a queue stack.
// Some variable declarations and initialization actions
// Access the current node
Inv-> marked = 1; // when the marked value is 1, no access is required.
Visit (INV );
Do
{
Flag2 = 0;
// Flag2 is an important flag variable used to describe the number of all unaccessed nodes on the current node. Two or more of them are represented by 2.
// Flag2: 0: current node has no adjacent which has not been visited.
// 1: current node has only one adjacent node which has not been visited.
// 2: current node has more than one adjacent node which have not been visited.
V1 = firstadjacent (ingraph, inv); // adjacent point V1
While (V1! = NULL) // access all adjacent contacts of the current node
{
If (V1-> marked = 0 )//..
{
If (flag2 = 0) // The adjacent contacts of the current node have 0 unaccessed
{
// First, access the leftmost Node
Visit (V1 );
V1-> marked = 1; // access completed
Flag2 = 1 ;//
// Records the leftmost son
Lchildv = V1;
// Save the current node's first unvisited (has been visited at this time) adjacent node
}
Else if (flag2 = 1) // The adjacent point of the current node has one unaccessed
{
// Create a queue, apply for space, and add the first node
Flag2 = 2;
}
Else if (flag2 = 2) // two adjacent contacts of the current node are not accessed.
{
EnQueue (tmpQ, v1 );
}
}
V1 = nextAdjacent (inGraph, inV, v1 );
}
If (flag2 = 2) // push adjacent nodes which are not visited.
{
// Store the pressure stacks of the first 1 unaccessed adjacent nodes on the current node.
Seqpush (teststack, tmpq );
Inv = lchildv;
}
Else if (flag2 = 1) // only has one adjacent which has been visited.
{
// If there is only one leftmost son, set the current vertex to leftmost son.
Inv = lchildv;
}
Else if (flag2 = 0)
// Has no adjacent nodes or all adjacent nodes has been visited
{
// When the adjacent contacts of the current node have been accessed or no adjacent contacts need to be returned, the queue element pops up from the queue node on the top of the stack,
// The Node elements in the queue are queued in sequence. If the nodes are accessed, the queue continues to be queued (when the current queue node is empty,
// Continue to exit the stack, and the queue at the top of the next stack will pop up until there is an unaccessed node (the current point of access concurrency) or until the stack is empty.
Flag = 0;
While (! Isnullseqstack (teststack )&&! Flag)
{
V1 = frontqueueinst (teststack); // return the first element of the queue in the top node of the stack.
Dequeueinst (teststack); // bring up the first element of the queue in the top node of the stack
If (V1-> marked = 0)
{
Visit (V1 );
V1-> marked = 1;
Inv = V1;
Flag = 1;
}
}
}
} While (! IsNullSeqStack (testStack); // the algorithm ends when the stack is null
}
-----------------------------
Description of the above procedures:
Therefore, the data structure that should be used here should adopt the following form:
1) in the implementation of the queue, each queue node is the node pointer type in the figure.
Define an annular queue with The subscripts at the end of the queue plus the queue length as follows:
Struct SingleRearSeqQueue;
Typedef PVexType QElemType;
Typedef struct SingleRearSeqQueue * PSingleRearSeqQueue;
Struct SingleRearSeqQueue
{
Int rear;
Int quelen;
QElemType dataPool [MAXNUM];
};
Other basic operations are not described here.
2) in the implementation of the stack, each node element in the stack is a pointer to the queue, which is defined as follows:
# Define SEQ_STACK_LEN 1000
# Define StackElemType PSingleRearSeqQueue
Struct SeqStack;
Typedef struct SeqStack * PSeqStack;
Struct SeqStack
{
StackElemType dataArea [SEQ_STACK_LEN];
Int slot;
};
To provide better encapsulation, two special operations are implemented for this stack.
2.1) The deQueueInSt operation is used to pop up the first element of the queue in the top node of the stack.
Void deQueueInSt (PSeqStack inStack)
{
If (isEmptyQueue (seqTop (inStack) | isNullSeqStack (inStack ))
{
Printf ("in deQueueInSt, under flow! /N ");
Return;
}
DeQueue (seqTop (inStack ));
If (isEmptyQueue (seqTop (inStack )))
InStack-> slot --;
}
2.2) The frontqueueinst operation is used to return the first element of the queue in the top node of the stack.
Qelemtype frontqueueinst (pseqstack instack)
{
If (isemptyqueue (seqtop (instack) | isnullseqstack (instack ))
{
Printf ("in frontqueueinst, under flow! /N ");
Return '/R ';
}
Return getheaddata (seqtop (instack ));
}
==============================
OK. This article is complete.
July and July January 1, 2011. Happy 2011 New Year!
Author's statement:
I have copyright to all the content and materials of this blog. For more information, please indicate the author's July and its source.
Always pay tribute to you. Thank you. July and July December 2, 2010.
This article from the CSDN blog, reproduced please indicate the source: http://blog.csdn.net/v_JULY_v/archive/2011/01/01/6111353.aspx