void Graph::dijkstra_shortest_path(int root, bool isTerminateAsFound){ //<length nodeid > tricky nodes[i]为节点i在heap中的指针 MinBinaryHeap<int, int > q; //优先队列 vector <BinaryHeapNode<int, int >*> nodes(n); int min,w; //min 最小权值对应的节点id, w为与min相连的节点id for (int i = 0; i < n; ++i){ distance[i] = POSTIVE_MAXINT; parent[i] = -1; if ( i == root ) { distance[i] = 0; parent[i] = i; } nodes[i] = q.insert(distance[i],i); } while(!q.empty()){ min = q.minimum()->data(); if (isTerminateAsFound && min==dest){ //必须等到dest出优先队列才能结束,因为以后都不可能对其松弛 break; } if (q.minimum()->key() == POSTIVE_MAXINT){ break; } //后面的都是其他森林,不需要遍历 q.removeMinimum(); nodes[min] = NULL; //开始更新和u相连的边 relax list<Node>::iterator itr = linktable[min].begin(); while(itr != linktable[min].end()){ w = itr->id; if (nodes[w] != NULL) //未被选中加入S { if (distance[min]+itr->weight < distance[w]) //relax { q.decreaseKey(nodes[w], distance[min]+itr->weight); distance[w] = distance[min]+itr->weight; parent[w] = min; } } ++itr; } } }
void Graph::dijkstra_without_pass_other_mustpass_nodes(int root){ //<length nodeid > tricky nodes[i]为节点i在heap中的指针 MinBinaryHeap<int, int > q; //优先队列 vector <BinaryHeapNode<int, int >*> nodes(n); int min,w; //min 最小权值对应的节点id, w为与min相连的节点id for (int i = 0; i < n; ++i){ distance[i] = POSTIVE_MAXINT; parent[i] = -1; if ( i == root ) { distance[i] = 0; parent[i] = i; } nodes[i] = q.insert(distance[i],i); } while(!q.empty()){ min = q.minimum()->data(); // if (min==end) break; //必须等到end出优先队列才能结束,因为以后都不可能对其松弛 if (q.minimum()->key() == POSTIVE_MAXINT){ break; } //后面的都是其他森林,不需要遍历 q.removeMinimum(); nodes[min] = NULL; //除root以外其他必过节点成为黑洞,没有出边,不帮助松弛 if ((min != root )&&(allmustpass.find(min) != allmustpass.end())) continue; //开始更新和u相连的边 relax list<Node>::iterator itr = linktable[min].begin(); while(itr != linktable[min].end()){ w = itr->id; if (nodes[w] != NULL){ //未被选中加入S if (distance[min]+itr->weight < distance[w]){ //relax q.decreaseKey(nodes[w], distance[min]+itr->weight); distance[w] = distance[min]+itr->weight; parent[w] = min; } } ++itr; } } }
bool test_insert_deleteMin(int numItems) { MinBinaryHeap h; bool failed = false; int i; for (i = 0; i < numItems; i++) { h.insert(new IntegerData(i)); } for(i = 0; i < numItems; i++ ) { IntegerData * x = (IntegerData*)h.deleteMin(); if( x->value != i ) { cout << "Oops! " << i << " != " << x->value << endl; failed = true; } delete x; } if (failed) { cout << "insert/remove 0:9999 failed" << endl; } else { cout << "insert/remove 0:9999 successful" << endl; } return failed; }
bool test_random(int numItems) { MinBinaryHeap h; Container ** nodePointers = new Container * [numItems]; IntegerData ** values = new IntegerData * [numItems]; bool failed = false; int i; for (i = 0; i < numItems; i++) { // need to be careful not to work with data that is near integer max or min value values[i] = new IntegerData(rand() % numItems); nodePointers[i] = h.insert(values[i]); } failed = false; for (i = 0; i < numItems; i++) { // need to be careful not to work with data that is near integer max or min value // because if we subtract from min or add to max we get overflow (undefined behavior) if (i % 2 == 0) { values[i]->value -= rand() % numItems; h.decreaseKey(nodePointers[i]); } else { values[i]->value += rand() % numItems; h.increaseKey(nodePointers[i]); } } IntegerData * x = (IntegerData*)h.deleteMin(); int lastValue = x->value; delete x; for(i = 1; i < numItems; i++ ) { x = (IntegerData*)h.deleteMin(); if( x->value < lastValue ) { cout << "Oops! " << x->value << " is not >= " << lastValue << endl; failed = true; } lastValue = x->value; delete x; } if (failed) { cout << "random test failed" << endl; } else { cout << "random test successful" << endl; } delete [] nodePointers; delete [] values; return failed; }
bool test_increase_decreaseKey(int numItems) { MinBinaryHeap h; Container ** nodePointers = new Container * [numItems]; IntegerData ** values = new IntegerData * [numItems]; bool failed = false; int i; for (i = 0; i < numItems; i++) { values[i] = new IntegerData(i); nodePointers[i] = h.insert(values[i]); } failed = false; for (i = 0; i < numItems; i++) { // decrease all the even ones by 1, increase all the odd ones by 9998 // should result in the sequence -1, 1, 3, ..., 9995, 9997, (odds + 9998)=9999, 10001... if (i % 2 == 0) { values[i]->value--; h.decreaseKey(nodePointers[i]); } else { values[i]->value+=9998; h.increaseKey(nodePointers[i]); } } for(i = 0; i < numItems; i++ ) { IntegerData * x = (IntegerData*)h.deleteMin(); if( x->value != (i*2-1) ) { cout << "Oops! " << (i*2-1) << " != " << x->value << endl; failed = true; } delete x; } if (failed) { cout << "decreaseKey evens/increaseKey odds 0:9999 failed" << endl; } else { cout << "decreaseKey evens/increaseKey odds 0:9999 successful" << endl; } delete [] nodePointers; delete [] values; return failed; }