Ii. Continued, Dijkstra algorithm + C Implementation of the Fibonacci heap

Source: Internet
Author: User

Ii. resumption, DijkstraAlgorithm+ Step-by-Step C Implementation of the Fibonacci heap

Author: July, March 18, 2011
Source:Http://blog.csdn.net/v_JULY_v
----------------------------------

 

Introduction:
To consider a problem,
Six Points on the plane, a, B, c, d, e, f. It is assumed that the distance between some points is known,
Now, the shortest distance from A to the other five points, B, C, D, E, and F is required.

As shown in:

After that, we can easily get the shortest distance of A-> B, C, D, E, F:

Destination path shortest distance
A => A, A-> A 0
A => B, A-> C-> B 3 + 2 = 5
A => C, A-> C 3
A => D, a-> C-> D 3 + 3 = 6
A => E, A-> C-> E 3 + 4 = 7
A => F, A-> C-> D-> F 3 + 3 + 3 = 9

I think, if you have just entered a blank question, you need to answer a-> B, c, d, e, f the shortest distance of each point,
A primary school student can fill out the information within a few minutes.

Of course our problem is not that simple. The above is just a concrete example.
In fact, many problems, such as the problem of finding the shortest path of a graph, need to use the above method to constantly compare and find the shortest path, it is the application of Dijkstra algorithm. Of course, there are BFS algorithms and more efficient a * search algorithms.

A * the search algorithm has been described in detail in this blog. In this article, we use the Fibonacci heap to implement the Dijkstra algorithm.
That is, Dijkstra + Fibonacci heap C implementation.

After studying an algorithm thoroughly, I want to writeCodeTo implement it is to truly master an algorithm. The classic Algorithm Research Series in this blog has been written18 articlesArticleThere are eleven algorithms, so there are more than 10 algorithms to implement.

Code style
To implement an algorithm, you must first understand the principle of this algorithm. After understanding the principle of this algorithm, you must write code for implementation.
Before opening the compiler, I first searched the internet for "Dijkstra algorithm + Fibonacci heap implementation ".

I found that no C code has been implemented by the Dijkstra + Fibonacci heap on the internet, and I skipped the following types of code:

1. No comments (not readable ).
2. No typographical layout (uncomfortable ).
3. Complicated redundancy (look at it with annoyance ).

 

Implement Dijkstra algorithm in the Fibonacci heap

OK. Let's get started with the subject. Next, let's use the Fibonacci heap to implement the Dijkstra algorithm step by step.
As mentioned above, to implement an algorithm, we must first clarify its principles and ideas, understand the principles of an algorithm, and know what the purpose of the algorithm is, that is, what is this algorithm used?

From the preceding example, we can conclude that the Dijkstra algorithm is used to solve the shortest path from a point to another point.
We always need to find the shortest distance from the source point to each target point. If a new point is found during the path searching process, it is found that the path can be shortened when the source point reaches the path of the Previous destination point through the newly discovered point, so we must update this Shortest Path in time.

OK. For example, if we first find a path, a-> B, the shortest distance of this path is 6, and then find the C point, if the path a-> C-> B is located, the shortest distance of A-> B is 5, which is smaller than the shortest distance 6 previously found, the shortest distance from A to B is 5, and the shortest path is a-> C-> B.

Okay. Now that we understand what this algorithm is for, let's try to write it with pseudo code (some people may say, no, I haven't understood anything yet, I have to write code. Well, don't you have materials at hand? If you have to do all your work on your own, it's a huge project. : D .).

First, let's look at the pseudo code of the Dijkstra algorithm from the introduction to algorithms as follows:

Dijkstra (G, W, S)
1 initialize-single-source (G, S) // 1. initialize the node.
2 S ø
3 Q 1_v [g] // 2. Insert a node
4 While Q =ø
5 do u distinct EXTRACT-MIN (q) // 3. Extract the minimum point from the smallest queue
6 s ← s limit {u}
7 For each vertex v ε adj [u]
8 do relax (U, V, W) // 4. Relaxation operation.

After all, there is a lot of work to do with the code that can be compiled and run on the machine.
First, let's take a look at the above pseudo code. We can see that basically, this Dijkstra algorithm is mainly divided into the following four steps:

1. initialize node work
2. Insert a node
3. Extract the smallest vertex from the smallest queue
4. Relaxation operation.
 

OK. Because 2nd operations involve the Fibonacci heap, it is a little more complicated. Let's analyze 1st, 2, and 4 Operations first:

1. The O (v) time is used to estimate the shortest path and initialize the precursor.

Initialize-single-source (G, S)
1 for each vertex v ε v [g]
2 Do D [v] ← ∞
3 π [v] rjnil // o (V)
4 d [s] 0

Based on the above pseudo code, it is not difficult to write the following code:

Void init_single_source (graph * g, int S)
{
For (INT I = 0; I <G-> N; I ++ ){
D [I] = inf;
Pre [I] =-1;
}
D [s] = 0;
}

2. Insert a node to the queue

2 S ø
3 Q 1_v [g] // 2. Insert a node

Code:
For (I = 0; I <G-> N; I ++)
S [I] = 0;

4. Relaxation operation.
first, you need to understand what is a relaxation operation:
the Dijkstra algorithm uses the relaxation technology to <-V, set a property D [v] to describe the upper bound of the weight of the shortest path from the source point S to V, which is called the estimation of the shortest path.
relax (U, V, W)
1 if d [v]> d [u] + W (u, v)
2 then d [v] ← d [u] + W (u, v)
3 π [v] ← U // o (E)

similarly, we can easily write the following code:
void relax (int u, int V, graph * g)
{< br> If (d [v]> d [u] + G-> W [u] [v])
{< br> d [v] = d [u] + G-> W [u] [v]; /// Update the Shortest Path
pre [v] = u; /// parent node with u As v
}< BR >}

Let's explain the above relax code.,Where U is the parent node of V. When it finds that its parent node D [u] is added with the Path Distance G-> W [u] [v], the shortest distance from the child node to the source node D [v] must be updated.
Please note that,To be clear:The original path from A to B is a-> B. It is found that when a passes through C to B, the path distance is shorter than a-> B. Of course, update the shortest path from A to B, that is, a-> C-> B, and C are the parent node of B. (in this case, I believe you are clear. : D .).
That is, a => B<=A-> C-> B: assign values.

OK, 1st, 2, and 4 operation steps. We have all written code for implementation. Then, let's write the code for 3rd operations: 3. From the smallest queue, extract the smallest vertex.

As you can see, we need to construct a minimum priority queue. What is used to construct the minimum priority queue column? By the way, heap. Which of the following is the best heap and the most efficient.

Why? OK. See the comparison of the three implementation methods of the minimum priority queue:

EXTRACT-MIN + Relax
I. Simple Method: O (V * V + E * 1)
Ii. Binary cross/item heap: O (V * LGV + | E | * LGV)
Source point reachable: O (E * LGV)
Sparse graph with E = O (V ^ 2/LGV ),
=> O (V ^ 2)
Iii. Fibonacci heap: O (V * LGV + E)

Where V is the vertex and E is the edge. Okay, so we can see that in the Dijkstra algorithm, when the Fibonacci heap is used as the priority queue, the algorithm's time complexity isO (V * LGV + E).

So what columns are we going to do next? Of course, it is necessary to implement a Fibonacci heap. How can we implement it before we can use it?
Column in Dijkstra algorithm? By the way, write it as a database. Library? It is a class.

OK. Here is the implementation of the Fibonacci heap:// Fibonacciheap. h <br/> # ifndef _ maid _ <br/> # DEFINE _ maid _ </P> <p> # include <functional> <br/> # include <algorithm> </P> <p> template <typename T> <br/> struct fib_node <br/> {<br/> fib_node * NS _; // post-drive node <br/> maid * Pt _; // parent node <br/> maid * PS _; // precursor node <br/> maid * FC _; // header node <br/> int rank _; // child node <br/> bool marked _; // whether the child node is deleted <br/> T * PV _; <br/> fib _ Node (T * Pv = 0): PV _ (PV) {}< br/> T & Value (void) {return * PV _;} <br/> void set_src (T * PV) {PV _ = PV ;}< br/> }; // data structure of fib_node </P> <p> template <class node, class OD> <br/> node * merge_tree (node * a, node * B, OD small) // merge nodes <br/>{< br/> If (small (B-> value (), A-> value () <br/> swap (, b); <br/> node * fc = A-> FC _; <br/> A-> FC _ = B; <br/> A-> NS _ = A-> PS _ = A-> Pt _ = 0; <br/> + A-> rank _; </P> <p> B-> PT _ = A; // parents whose A is B <br/> B-> NS _ = FC; // The first node is assigned to the precursor Node B <br/> B-> PS _ = 0; <br/> If (FC! = 0) <br/> FC-> PS _ = B; <br/> return; <br/>}</P> <p> template <typename node> <br/> void erase_node (node * me) // Delete the node <br/>{< br/> node * const P = me-> Pt _; <br/> -- p-> rank _; <br/> If (p-> FC _ = me) // if me is a header node <br/>{< br/> If (P-> FC _ = me-> NS _)! = 0) <br/> me-> NS _-> PS _ = 0; <br/>}< br/> else <br/> {<br/> node * Prev = me-> PS _; <br/> node * Next = me-> NS _; // It may be 0 <br/> Prev-> NS _ = next; <br/> If (next! = 0) <br/> next-> PS _ = Prev; <br/>}</P> <p> template <class node, class OD> <br/> node * merge_fib_heap (node * a, node * B, OD small) // call the above merge_tree to merge the fiber _ heap. <Br/>{< br/> Enum {size = 64}; // <br/> node * V [size] = {0}; <br/> int K; <br/> while (! = 0) <br/>{< br/> node * Carry = A; <br/> A = A-> NS _; <br/> for (k = carry-> rank _; V [k]! = 0; ++ K) <br/>{< br/> carry = merge_tree (carry, V [K], small ); <br/> V [k] = 0; <br/>}< br/> V [k] = carry; <br/>}< br/> while (B! = 0) <br/>{< br/> node * Carry = B; <br/> B = B-> NS _; <br/> for (k = carry-> rank _; V [k]! = 0; ++ K) <br/>{< br/> carry = merge_tree (carry, V [K], small ); <br/> V [k] = 0; <br/>}< br/> V [k] = carry; <br/>}< br/> node ** T = STD: Remove (V, V + size, (node *) 0 ); <br/> int const n = T-V; <br/> If (n> 0) <br/> {<br/> for (k = 0; k <n-1; + + k) <br/> V [k]-> NS _ = V [k + 1]; <br/> for (k = 1; k <n; ++ K) <br/> V [k]-> PS _ = V [k-1]; <br/> V [n-1]-> NS _ = V [0]-> PS _ = 0; <br/>}< br/> return V [0]; <br/>}< /P> <p> template <typename T, class OD = STD :: less <t> <br/> struct min_fib_heap // extract the smallest node <br/> {<br/> typedef fib_node <t> node; <br/> typedef node node_type; </P> <p> node * roots _; <br/> node * min _; // pointer to the minimum node <br/> OD less _; </P> <p> min_fib_heap (void): roots _ (0), min _ (0), less _ () {}< br/> bool empty (void) const {return roots _ = 0 ;}< br/> T & Top (void) const {return min _-> value () ;}</P> <p> void decrease_key (node * Me) // Delete <br/>{// precondition: root _ Not zero <br/> If (less _ (Me-> value (), min _-> value () <br/> min _ = me; <br/> cascading_cut (me); <br/>}< br/> void push (node * me) // press <br/>{< br/> me-> Pt _ = me-> FC _ = 0; <br/> me-> rank _ = 0; <br/> If (roots _ = 0) <br/>{< br/> me-> NS _ = me-> PS _ = 0; <br/> me-> marked _ = false; <br/> roots _ = min _ = Me; <br/>}< br/> else <br />{< Br/> If (less _ (Me-> value (), min _-> value () <br/> min _ = me; <br/> insert2roots (me); <br/>}< br/> node * Pop (void) // <br/>{< br/> node * const om = min _; <br/> erase_tree (min _) appears _); <br/> min _ = room _ = merge_fiber _ heap (room _, min _-> FC _, less _); <br/> If (room _! = 0) // find new min _ <br/>{< br/> for (node * t = roots _-> NS _; t! = 0; t = T-> NS _) <br/> If (less _ (t-> value (), min _-> value ())) <br/> min _ = T; <br/>}< br/> return om; <br/>}< br/> void Merge (void) // merge <br/>{< br/> If (empty () return; <br/> min _ = roots _ = merge_fib_heap (roots _, (node *) 0, less _); <br/> for (node * A = roots _-> NS _;! = 0; A = A-> NS _) <br/> If (less _ (a-> value (), min _-> value ())) <br/> min _ = A; <br/>}< br/> PRIVATE: <br/> void insert2roots (node * me) // insert <br/> {// precondition: 1) Root _! = 0; 2) Me-> value ()> = min _-> value () <br/> me-> Pt _ = me-> PS _ = 0; <br/> me-> NS _ = roots _; <br/> me-> marked _ = false; <br/> roots _-> PS _ = me; <br/> roots _ = Me; <br/>}< br/> void cascading_cut (node * Me) // disconnect <br/> {// precondition: me is not a root. that is me-> Pt _! = 0 <br/> for (node * P = me-> Pt _; P! = 0; me = P, P = p-> Pt _) <br/>{< br/> erase_node (me); <br/> insert2roots (me ); <br/> If (p-> marked _ = false) <br/>{< br/> P-> marked _ = true; <br/> break; <br/>}< br/> void erase_tree (node * me) // Delete <br/>{< br/> If (roots _ = Me) <br/>{< br/> roots _ = me-> NS _; <br/> If (roots _! = 0) <br/> roots _-> PS _ = 0; <br/>}< br/> else <br/> {<br/> node * const Prev = me-> PS _; <br/> node * const next = me-> NS _; <br/> Prev-> NS _ = next; <br/> If (next! = 0) <br/> next-> PS _ = Prev; <br/>}< br/> }; // min_fib_heap class </P> <p> template <typename Fitr> <br/> bool is_sorted (Fitr first, Fitr last) <br/>{< br/> If (first! = Last) <br/> for (Fitr Prev = first ++; first! = Last; Prev = first ++) <br/> If (* First <* PREV) return false; <br/> return true; <br/>}< br/> template <typename Fitr, class OD> <br/> bool is_sorted (Fitr first, Fitr last, od cmp) <br/>{< br/> If (first! = Last) <br/> for (Fitr Prev = first ++; first! = Last; Prev = first ++) <br/> If (CMP (* First, * PREV) return false; <br/> return true; <br/>}

Since this blog will elaborate on the operations of this Fibonacci heap in the future, I will not explain it hereProgram.

OK, implements the Fibonacci heap. Next, we can write the Dijkstra algorithm code. For the sake of clarity, I once again paste the pseudo code of this algorithm:

Dijkstra (G, W, S)
1 initialize-single-source (G, S)
2 S ø
3 Q 1_v [g] // 3rd rows, insert operation, O (1)
4 While Q =ø
5 do u done EXTRACT-MIN (q) // 5th rows, EXTRACT-MIN operation, V * LGV
6 s ← s limit {u}
7 For each vertex v ε adj [u]
8 do relax (U, V, W) // 8th rows, relax operation, E * O (1)

The C code of the Dijkstra algorithm is as follows:Void Dijkstra (int s, T d [], int P []) <br/>{< br/> // find the shortest path from vertex s, in D, the shortest path of S-> I is stored. <br/> // P stores the parent node of I. <br/> If (S <1 | S> N) <br/> throw outofbounds (); </P> <p> // list of vertices that can be reached by path. The above Implementation of the Fibonacci heap code can be used here. <Br/> chain <int> L; </P> <p> chainiterator <int> I; <br/> // initialize D, P, and l <br/> for (INT I = 1; I <= N; I ++) <br/> {<br/> d [I] = A [s] [I]; </P> <p> If (d [I] = noedge) <br/>{< br/> P [I] = 0; <br/>}< br/> else <br/>{< br/> P [I] = s; <br/> L. insert (0, I); <br/>}</P> <p> // update d, P <br/> while (! L. isempty () <br/>{< br/> // find the vertex v of the minimum d <br/> int * V = I. initialize (l); <br/> int * w = I. next (); <br/> while (w) <br/>{< br/> If (d [* w] <D [* V]) <br/> V = W; </P> <p> W = I. next (); <br/>}</P> <p> int I = * V; <br/> L. delete (* V); <br/> for (Int J = 1; j <= N; j ++) <br/>{< br/> if (a [I] [J]! = Noedge <br/> &&(! P [J] | D [J]> d [I] + A [I] [J]) // d [I] is the parent node <br/>{< br/> // refresh a smaller d [J] <br/> d [J] = d [I] + A [I] [J]; </P> <p> // If J does not have a parent node, add it to L <br/> If (! P [J]) <br/> L. insert (0, J); </P> <p> // update the parent node <br/> P [J] = I; <br/>}< br/>}

Better code is still being corrected. In the future, the whole project will be released after the improvements are completed.

.

 

Copyright. Repost any article in this blog. Please use a hyperlink to indicate the source. Thank you.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.