最短路径的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写成+1 if (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 fugure int 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; } };
Geeks : Dijkstra’s Algorithm for Adjacency List Representation 最短路径,布布扣,bubuko.com
Geeks : Dijkstra’s Algorithm for Adjacency List Representation 最短路径
原文地址:http://blog.csdn.net/kenden23/article/details/27523185