- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试使用 Prim 的最小生成树算法优化图形。但我没有得到想要的答案。
算法:
1. Construct min heap array. The array consists of nodes which have a vertex value
and a key value. The key values are initialized to INT_MAX initially.
2. Make the zeroth node's key 0, as this is the starting node.
3. I iterate over the heap, till it becomes empty, and in every step following is done:
- Extract the minimum element out of the min heap. This is done by extractMin()
function in the class MinHeap.
4. Look for this extracted element's neighbors and update their keys based on the weight of
the corresponding edge.
5. Then decrease the key value in the minHeap by using decreaseKey() function in
class MinHeap.
6. Store the parent and child for which the condition satisfies in a map called parent.
这是代码说明:
1. The code contains two header files, Graph.h and MinHeap.h. The functions are all std f
functions in these files. So there won't be any problem in understanding them.
2. The Graph.cpp file contains the PrimMST() function which does all the job and performs
the entire algorithm.
问题是:
1. When I extract a node from heap in PrimMST() function, I call extractMin() function
defined in MinHeap.cpp file. This function swaps the top most node in the heap with the
bottom most node. And then performs the heapify operation.
But, it is not performing this operation though I have called it in extractMin(). There's
no problem with minHeapify function which does the heapify operation as it does
perform its job else where is the program.
这是程序:P.S.:我发布了包含所有头文件的完整代码,以便于理解。但跳过代码,请观察Graph.cpp文件中的PrimMST()函数。
/***************GRAPH.H*******************************/
#ifndef GRAPH_H_
#define GRAPH_H_
#include <list>
#include <map>
using namespace std;
class AdjListNode{
int v;
int weight;
public:
AdjListNode(int _v, int _w){ v = _v; weight = _w; }
int getV() { return v; }
int getWeight() { return weight; }
};
class Graph{
int V; // To store number of vertices in the graph
list<AdjListNode> *adj; // This is a map for storing the adjacency list
map<int,int> mapping; // A map to form a dictionary of vertex values to their array indexes for look ups.
map<int,int> parent; // A map to store the parent child for a given edge in the graph
public:
Graph(int); // Class constructor
void HashTable(int *, int); // This method uses the map library in STL to create a mappinh
// of arbitrary integers to zero based array indexes
int getHashedElt(int); // This method returns the value corresponding to a given
// key in a hash table
void addEdge(int, int, int); // This method adds the second arg to the adj list of first arg.
void printGraph(); // This method prints the adjacency list of all the vertices
void PrimMST(int *, int); // This function will perform the Prim's MST algorithm and optimize
// the number of nodes in the graph
};
#endif
/****************GRAPH.CPP*************************/
#include <iostream>
#include <climits>
#include <list>
#include <map>
#include "Graph.h"
#include "MinHeap.h"
#define INF 9999
using namespace std;
Graph::Graph(int v){
V = v;
adj = new list<AdjListNode>[V];
}
// This function takes in a pointer to array and its size as its arguments to create a hashtable.
// So. if you have 10,11,12,13,14,15 as the nodes.
// Create an array int arr[] {10,11,12,13,14,15}, and int size = sizeof(arr)/sizeof(arr[0])
// And pass it to this function this creates a dictionary named mapping for O(1) look up of
// index by other functions.
void Graph::HashTable(int *nodeData, int size){
for (int i = 0; i < size; i++){
mapping[nodeData[i]] = i;
}
return;
}
// This method returns the value corresponding to a particular node in constant time.
int Graph::getHashedElt(int data){
return mapping[data];
}
// This function creates an adjacency list for every vertex in the graph
void Graph::addEdge(int node1, int node2, int weight){
AdjListNode node(node2, weight);
int index = getHashedElt(node1);
adj[index].push_back(node);
}
void Graph::printGraph(){
list<AdjListNode>::iterator j;
int i = 0;
while (i<V){
for (j = adj[i].begin(); j != adj[i].end(); j++){
cout <<"(" << j->getV() << "," << j->getWeight() << ")->";
}
if (!adj[i].empty())
cout << "NULL\n";
i++;
}
}
void Graph::PrimMST(int *arr, int size){
MinHeap minHeap(arr,size);
size_t key[V]; // Key values to pick minimum weight edge in cut
for (int i = 1; i < V; i++){
parent[arr[i]] = -1; // All the parents are -1 initially
key[i] = INT_MAX; // Initially all the keys are initialised to positive infinity
MinHeapNode *newNode = minHeap.newMinHeapNode(arr[i],key[i]);
//cout << "("<< arr[i] << ", " << key[i] << ")\n";
minHeap.insertNode(i, newNode);
}
// Make key value of 0th vertex as 0 so that it is extracted first.
key[0] = 0;
// This function insertNode creates a newNode with vertex number and associated key value.
MinHeapNode *newNode = minHeap.newMinHeapNode(arr[0],key[0]);
minHeap.insertNode(0, newNode);
//minHeap.printHeap();
while (!minHeap.isEmpty()){
// Extract the vertex with minimum key value
minHeap.printHeap();
MinHeapNode *minNode = minHeap.extractMin();
// Get the vertex of this minNode.
int u = minNode->v;
cout << "\n";
minHeap.printHeap();
cout << "\n\n\n";
//cout << u << "\n";
// Traverse through all the adjacent vertices of u (extended vertex)
// and update their key values
list<AdjListNode>::iterator j;
for (j = adj[mapping[u]].begin(); j != adj[mapping[u]].end(); j++) {
int v = j->getV();
// If v is not yet included in the MST and weight of u-v
// is less than key value of v, then update key value
// and parent of v
if (minHeap.isInMinHeap(v) && j->getWeight() < key[mapping[v]]){
key[mapping[v]] = j->getWeight();
// cout << key[mapping[v]] << "\n";
parent[v] = u;
minHeap.decreaseKey(v,key[mapping[v]]);
}
}
}
for (int k = 1; k < size; k++){
//cout <<parent[arr[k]]<<"---"<<arr[k]<< "\n";
}
return;
}
/*************MINHEAP.H**************************/
#ifndef MINHEAP_H_
#define MINHEAP_H_
#include <map>
using namespace std;
struct MinHeapNode{
int v;
size_t key;
};
class MinHeap{
int size; // Number of heap nodes present in the heap at any given time
int capacity; // Capacity of min heap
map<int,int> pos; // This is map which stores the array index of a given vertex, for O(1) look up
MinHeapNode **MinHeapArray; // This array containe pointers to all the heap nodes.
public:
MinHeap(int*,int); // Class constructor, it will allocate space to minHeap and initialise all the variables.
// It also creates the map of every vertex to an index, so that there is O(1) look up.
MinHeapNode *newMinHeapNode(int,size_t); // This function creates a new min heap node with a given value of vertex and weight
int getIndex(int); // This function returns the index of a given vertex in pos map.
void insertNode(int,MinHeapNode *); // This function inserts a node into the MinHeapArray.
void printHeap();
void swapMinHeapNode(MinHeapNode **, MinHeapNode **); // It will perform swap operation in the heap.
void minHeapify(int); // Standard function to heapify at given idx.
bool isEmpty(); // A utility function to check whether given heap is empty or not.
bool isInMinHeap(int); // Checks whether given vertex in the heap or not
MinHeapNode *extractMin(); // Std func to extract to minimum node from the heap.
void decreaseKey(int,int); // This func performs the decreaseKey op by making use of pos map.
};
#endif
/***************MINHEAP.CPP***************************/
#include <iostream>
#include <cstdlib>
#include <climits>
#include <map>
#include "MinHeap.h"
using namespace std;
MinHeap::MinHeap(int *arr,int s){
size = 0;
capacity = s;
MinHeapArray = (MinHeapNode **)malloc(sizeof(MinHeapNode *)*s);
for (int i = 0; i < s; i++){
pos[arr[i]] = i; // This is a mapping from vertex to array index i. This will enable O(1) access of any var in heap.
}
}
MinHeapNode *MinHeap::newMinHeapNode(int v, size_t key){
MinHeapNode *node = new MinHeapNode;
node->v = v;
node->key = key;
return node;
}
int MinHeap::getIndex(int v){
return pos[v];
}
void MinHeap::insertNode(int idx, MinHeapNode *node){
MinHeapArray[idx] = node;
size++;
}
bool MinHeap::isEmpty(){
return size == 0;
}
bool MinHeap::isInMinHeap(int v){
if (pos[v] < size)
return true;
return false;
}
void MinHeap::printHeap(){
for (int i = 0; i < size; i++){
cout << MinHeapArray[i]->v << ", "<< MinHeapArray[i]->key << "\n";
}
}
void MinHeap::swapMinHeapNode(MinHeapNode **a, MinHeapNode **b){
MinHeapNode *t = *a;
*a = *b;
*b = t;
}
// A standard function to heapify at given index idx
// This function also updates position of nodes when they are swapped.
void MinHeap::minHeapify(int idx){
int smallest, left, right;
left = (2*idx + 1);
right = (2*idx + 2);
smallest = idx;
if (left < size && MinHeapArray[left]->key < MinHeapArray[smallest]->key)
smallest = left;
if (right < size && MinHeapArray[right]->key < MinHeapArray[smallest]->key)
smallest = right;
if (smallest != idx){
// To nodes to be swapped in min heap
MinHeapNode *smallestNode = MinHeapArray[smallest];
MinHeapNode *idxNode = MinHeapArray[idx];
// Change the mapping of vertices in pos map.
pos[smallestNode->v] = idx;
pos[idxNode->v] = smallest;
// Swap Nodes using swapMinHeapNode utility function
MinHeap::swapMinHeapNode(&smallestNode, &idxNode);
minHeapify(smallest);
}
return;
}
MinHeapNode *MinHeap::extractMin(){
if (isEmpty())
return NULL;
// Store the root node
MinHeapNode *root = MinHeapArray[0];
// Replace the root with last node
MinHeapNode *lastNode = MinHeapArray[size-1];
MinHeapArray[0] = lastNode;
// Update position of last node
pos[root->v] = size - 1;
pos[lastNode->v] = 0;
// Reduce heap size and heapify root
size--;
MinHeap::minHeapify(0);
return root;
}
void MinHeap::decreaseKey(int v, int key){
// Get the index of v in heap array
int i = pos[v];
// Get the node and update its key value
MinHeapArray[i]->key = key;
// Travel up till the complete tree is not heapified.
// This is O(logn) loop
while (i && MinHeapArray[i]->key < MinHeapArray[(i-1)/2]->key){
// Swap this node with its parent
// First update the pos matrix
pos[MinHeapArray[i]->v] = (i-1)/2;
pos[MinHeapArray[(i-1)/2]->v] = i;
// Do the swapping now.
MinHeap::swapMinHeapNode(&MinHeapArray[i], &MinHeapArray[(i-1)/2]);
// move to the parent index in the next iteration
i = (i - 1)/2;
}
return;
}
/**********************MAIN FUNCTION CALL***************/
#include <iostream>
#include "Graph.h"
#include "MinHeap.h"
using namespace std;
int main(){
int arr[] = {0,1,2,3,4,5,6,7,8}; // An array with all the vertices
int size = sizeof(arr)/sizeof(arr[0]);
Graph g(size);
g.HashTable(arr,size);
g.addEdge(0, 1, 4);
g.addEdge(0, 7, 8);
g.addEdge(1, 2, 8);
g.addEdge(1, 7, 11);
g.addEdge(2, 3, 7);
g.addEdge(2, 8, 2);
g.addEdge(2, 5, 4);
g.addEdge(3, 4, 9);
g.addEdge(3, 5, 14);
g.addEdge(4, 5, 10);
g.addEdge(5, 6, 2);
g.addEdge(6, 7, 1);
g.addEdge(6, 8, 6);
g.addEdge(7, 8, 7);
//g.printGraph();
g.PrimMST(arr,size);
return 0;
}
有了这个输入,我得到了错误的输出。请注意,此输出是通过在调用 extractMin() 之前和之后调用 printHeap 获得的。并且可以看出,即使每次提取节点时在 extractMin() 中调用 minHeapify(0)。它以某种方式不执行该操作,因此堆未堆化,导致错误结果 示例输出,前 3 次迭代:
First Iteration:
0, 0
1, 2147483647
2, 2147483647
3, 2147483647
4, 2147483647
5, 2147483647
6, 2147483647
7, 2147483647
8, 2147483647
8, 2147483647
1, 2147483647
2, 2147483647
3, 2147483647
4, 2147483647
5, 2147483647
6, 2147483647
7, 214748364
Second Iteration:
1, 4
7, 8
2, 2147483647
8, 2147483647
4, 2147483647
5, 2147483647
6, 2147483647
3, 2147483647
3, 2147483647
7, 8
2, 2147483647
8, 2147483647
4, 2147483647
5, 2147483647
6, 2147483647
Third Iteration:
2, 8
7, 8
3, 2147483647
8, 2147483647
4, 2147483647
5, 2147483647
6, 2147483647
6, 2147483647
7, 8
3, 2147483647
8, 2147483647
4, 2147483647
5, 2147483647
请观察第二次和第三次迭代,它们根本没有堆化,即使我最后在 extractMin() 函数中调用了 minHeapify 函数。
我迫切需要这方面的帮助。
最佳答案
你的问题是在这一行 MinHeap::swapMinHeapNode(&smallestNode, &idxNode);
在 minHeapify(int idx)
中,你正在交换指向不存在的节点的指针要交换 MinHeapArray
中的值,您应该交换数组元素,所以这一行应该替换为 MinHeap::swapMinHeapNode(&MinHeapArray[idx], &MinHeapArray[smallest]);
关于c++ - Prim 的最小生成树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34645620/
我正在尝试用 javascript 创建一个随机迷宫生成器。 可能已经有可用的示例,但我正在尝试自己解决这个问题(好吧,尽可能多) 我遇到的问题是我的脚本只运行了几个 block 然后就停止了。 我认
一 点睛 在生成树的过程中,把已经在生成树中的节点看作一个集合,把剩下的节点看作另外一个集合,从连接两个集合的边中选择一条权值最小的边即可。 二 算法介绍 首先任选一个节点,例如节点1,把它放在集合
“因此,Prim 算法的总时间为 O(V lg V + E lg V) = O(E lg V),这与我们实现 Kruskal 算法的渐进时间相同。” 来自http://serverbob.3x.ro/
def prim(graph): que = queue.PriorityQueue() mst = [] visited = set() # Generate edg
我正在尝试使用优先级队列在 Java 中实现 Prim 的算法。 我找不到我的错误。 :/我只是认识到队列没有正确排序节点。 图表示例: 0 4 7 5 4 0 2 3 7 2 0 1 5 3 1 0
我的算法课正在讨论 Prim 算法作为一种寻找加权图的最小生成树的方法。我们的教授让我们试着想一个图的例子,Prim 的算法需要 N^2 时间来解决(N = 顶点数)。类没有人能凭空想到一个,所以我问
prim 算法的简单实现应该给出 O(mn) 的运行时间。但我在 Prim 函数中有 3 个 for 循环(使运行时间立方)。我哪里出错了? void Graph::Prim (const int s
我正在尝试实现一种近似算法来解决旅行商问题 (TSP),当三角不等式对边权重成立时可以使用该算法。正如 Cormen 等人在算法简介(第 3 3d.)中所述,伪代码是: 这是一个例子: 我苦恼的是如何
我发现 there are two ways to implement Prim algorithm ,并且邻接矩阵的时间复杂度为 O(V^2),而堆和邻接列表的时间复杂度为 O(E lg(V))。
我正在查看 Wikipedia entry对于 Prim 的算法,我注意到它与邻接矩阵的时间复杂度是 O(V^2),它与堆和邻接列表的时间复杂度是 O(E lg(V)),其中 E 是边数,V 是图中的
我正在尝试使用 Prim 的最小生成树算法优化图形。但我没有得到想要的答案。 算法: 1. Construct min heap array. The array consists of nodes
我有以下函数来查找父数组,以便使用 Prim 算法获得图的最小生成树。 #include #include #include int printMST(int parent[], int n, i
Prim 算法思想: 从任意一顶点 v0 开始选择其最近顶点 v1 构成树 T1,再连接与 T1 最近顶点 v2 构成树 T2, 如此重复直到所有顶点均在所构成树中为止。 最小生成树(MST):权值
这个问题在这里已经有了答案: what is the meaning of "let x = x in x" and "data Float#" in GHC.Prim in Haskell (2 个
所以我检查了之前发布的 prims 算法帖子。我找不到一个能满足老师要求的。我和他一起编写了这段代码,并且大部分工作正常。然而,由于某种原因,当它到达某个点时,它会破裂并走向错误的边缘。 '''pub
我必须从 Prim 算法创建一个迷宫,更准确地说是使用这个算法:(随机 Prim 算法)。 http://en.wikipedia.org/wiki/Maze_generation # Randomi
我正在尝试使用 Prim 算法实现一个随机生成的迷宫。但是该程序无法正确生成迷宫。请看看并给我一些建议 这是我的迷宫图片: 迷宫应该是这样的: Prim 算法: private void Prims(
我正在一个项目中使用 Dijkstra 算法,但想尝试使用策略模式实现 Prims 算法,看看它有什么更好的地方,但我不确定如何使用策略模式。我以前从未使用过模式,所以我不知道从哪里开始。 packa
我正在尝试将房间放置在 ASCII 屏幕上,然后使用 Prim's algorithm用迷宫“填充”房间之间的空间,但实际上并没有闯入房间。我已经修补了几个小时,但我无法找到一种方法来阻止我的算法闯入
我正在尝试使用 JGraphT 实现 Prim 的最小生成树算法。看起来怎么样? 我遇到的一个问题是 JGraphT 按照指示处理所有事情。因此,有时需要进行一些尴尬的调用来反转 g.getEdgeS
我是一名优秀的程序员,十分优秀!