Geeks : Dijkstra’s Algorithm for Adjacency List Representation 最短路径

来源:互联网 发布:流体力学仿真软件 编辑:程序博客网 时间:2024/06/04 18:57

最短路径的O(ElgV)的解法。

使用邻接表存储图,使用堆操作选取下一个最小路径点。

本题的难度并不在最短路径本身这个算法,而是在于堆的操作:

1 使用双重指针操作堆的节点,可以省去直接复制操作堆节点,提高效率,并且这才是有效操作动态地址数据的方法,不用双重指针,我思考了下,觉得更加不好做。

2 使用一个数组记录当前顶点在堆中的位置,相当于一个hash表了,可以需要的时候,直接从表中查找表示顶点的堆节点在堆中的位置,要记得更新节点时维护好这个表。

3 释放内存的时候注意,弹出堆的节点可以马上释放,不过注意不要双重释放内存了


记得曾经看到网上有人说堆排序是百万年薪的算法,不过现在看来光是堆排序是非常简单的算法了,会堆排序应该得达不到百万年薪吧,因为现在的算法高手应该都能随手写出堆排序的算法。

但是如本题这样灵活运用堆还是十分困难的。


参考:http://www.geeksforgeeks.org/greedy-algorithms-set-7-dijkstras-algorithm-for-adjacency-list-representation/


#include <stdio.h>#include <limits>class Dijsktra_Adjacency_List_and_Head{struct Node{int des, weight;Node *next;Node(int d, int w) : des(d), weight(w), next(NULL) {}~Node(){if (next) delete next;next = NULL;}};struct AdjList{Node *head;AdjList() : head(NULL) {}~AdjList(){if (head) delete head;head = NULL;}};struct Graph{int V;AdjList *arr;Graph(int v) : V(v){arr = new AdjList[v];}~Graph(){if (arr) delete [] arr;arr = NULL;}};void addEdge(Graph *graph, int src, int des, int wei){Node *n = new Node(des, wei);n->next = graph->arr[src].head;graph->arr[src].head = n;n = new Node(src, wei);n->next = graph->arr[des].head;graph->arr[des].head = n;}struct heapNode{int v, dist;heapNode(int v1, int d):v(v1), dist(d){}};struct minHeap{int size, capacity;int *pos;//记录顶点的位置//双重指针:直接操作地址,而不是复制数据heapNode **arr;explicit minHeap(int c = 0) : capacity(c), size(0){pos = new int[capacity];arr = new heapNode*[capacity];//创建存储空间}~minHeap(){if (pos) delete [] pos;for (int i = 0; i < size; i++){if (arr[i]) delete arr[i], arr[i] = NULL;}if (arr) delete [] arr;}};//双重指针的作用:这里只需要交换了地址,并不需要直接交换整个heapNode数据结构void swapMinHeapNode(heapNode **a, heapNode **b){heapNode *c = *a;*a = *b;*b = c;}void minheapify(minHeap *heap, int idx){int smallest, left, right;smallest = idx;left = idx * 2 + 1;right = idx * 2 + 2;//错误+2写成+1if (left < heap->size && heap->arr[left]->dist < heap->arr[smallest]->dist){smallest = left;}//很难调试的bug:下面不能加else,因为要选择三种中最小的if (right < heap->size &&heap->arr[right]->dist < heap->arr[smallest]->dist){smallest = right;}if (smallest != idx){heapNode *smallestNode = heap->arr[smallest];heapNode *idxNode = heap->arr[idx];heap->pos[smallestNode->v] = idx;heap->pos[idxNode->v] = smallest;swapMinHeapNode(&heap->arr[smallest], &heap->arr[idx]);minheapify(heap, smallest);}}bool isEmpty(minHeap *heap){return heap->size == 0;}heapNode *extraMin(minHeap *heap){if (isEmpty(heap)) return NULL;heapNode *root = heap->arr[0];heapNode *lastNode = heap->arr[heap->size-1];heap->arr[0] = lastNode;//swapMinHeapNode(&root, &lastNode);heap->pos[root->v] = heap->size-1;heap->pos[lastNode->v] = 0;--heap->size;minheapify(heap, 0);return root;}void decreaseKey(minHeap *heap, int v, int dist){int i = heap->pos[v];heap->arr[i]->dist = dist;while (i && heap->arr[i]->dist < heap->arr[(i-1)/2]->dist){heap->pos[heap->arr[i]->v] = (i-1)/2;heap->pos[heap->arr[(i-1)/2]->v] = i;swapMinHeapNode(&heap->arr[i], &heap->arr[(i-1)/2]);i = (i-1)/2;}}bool isInMinHeap(minHeap *heap, int v){if (heap->pos[v] < heap->size) return true;return false;}void printArr(int dist[], int n){printf("Vertex   Distance from Source\n");for (int i = 0; i < n; ++i)printf("%d \t\t %d\n", i, dist[i]);}void dijkstra(Graph *graph, int src, int dist[]){int V = graph->V;minHeap *heap = new minHeap(V);for (int i = 0; i < V; i++){dist[i] = INT_MAX;heap->arr[i] = new heapNode(i, dist[i]);heap->pos[i] = i;}dist[src] = 0;decreaseKey(heap, src, dist[src]);heap->size = V;while (!isEmpty(heap)){heapNode *hn = extraMin(heap);int u = hn->v;delete hn;hn = NULL;Node *pCrawl = graph->arr[u].head;while (pCrawl){int v = pCrawl->des;if (isInMinHeap(heap, v) && dist[u] != INT_MAX&& pCrawl->weight + dist[u] < dist[v]){dist[v] = pCrawl->weight + dist[u];decreaseKey(heap, v, dist[v]);}pCrawl = pCrawl->next;}}delete heap;}public:Dijsktra_Adjacency_List_and_Head(){// create the graph given in above fugureint V = 9;struct Graph* graph = new Graph(V);addEdge(graph, 0, 1, 4);addEdge(graph, 0, 7, 8);addEdge(graph, 1, 2, 8);addEdge(graph, 1, 7, 11);addEdge(graph, 2, 3, 7);addEdge(graph, 2, 8, 2);addEdge(graph, 2, 5, 4);addEdge(graph, 3, 4, 9);addEdge(graph, 3, 5, 14);addEdge(graph, 4, 5, 10);addEdge(graph, 5, 6, 2);addEdge(graph, 6, 7, 1);addEdge(graph, 6, 8, 6);addEdge(graph, 7, 8, 7);int *dist = (int *) malloc(sizeof(int) * V);dijkstra(graph, 0, dist);printArr(dist, V);free(dist);delete graph;}};



1 0
原创粉丝点击