I'm trying to implement the Ford Fulkerson Algorithm in C++.
However, I'm having trouble with my find_edge function. When I call this function in my_alg, it chooses the correct edge and then the flow is incremented in my_alg. It chooses the right edge and increment its flow (flow), but when I call the find_edge function again, the flow is not incremented as it should be.
This results in an endless loop of my algorithm. Probably I do something wrong with the pointers. You can see my code below.
//An object of this class represents an edge in the graph.
class Edge
{
private:
//Node *prev;
public:
int flow;
Edge(Node *firstNode, Node *secNode, unsigned inCost) {
orgNode = firstNode;
dstNode = secNode;
bridge_capacity = inCost;
}
Edge() {
flow=0;
}
};
//An object of this class holds a vertex of the graph
class Node
{
public:
Node *prev;
vector<Edge>& getAdjNodeList() {
return adjNodeList;
}
};
Edge *find_edge(Graph *g,Node *from,Node *to) {
vector<Edge> b=from->getAdjNodeList();
for(int i=0;i<b.size();i++) {
if(b[i].getDstNode()==to)
return (&b[i]);
}
return NULL;
}
int my_alg(Graph *as,Node *source,Node *sink){
Edge *find_edge();
int max_flow=0;
while(bfs(as,source,sink)) {
Node *b=as->nodeList[num_isl];
int inc=100000000;
while(b->prev!=NULL) {
Edge *bok=find_edge(as,b->prev,b);
inc=min(inc,bok->get_bridge_capacity()-bok->flow);
b=b->prev;
}
b=as->nodeList[num_isl];
while(b->prev!=NULL){
Edge *bok = find_edge(as,b->prev,b);
bok->flow += inc; // This is the place the flow is incremented
bout << bok->flow; // Here, everything is alright.
bok = find_edge(as,b->prev,b);
cout << bok->flow; // However, this is is not the correct result.
}
max_flow+=inc;
}
return max_flow;
}
I had a more thorough look at your code. To help you track your problems down yourself in the future, I will show you a sample process of finding the error.
If you really can not find the problem by looking at the code, you may want to strip down everything that obfuscates your view on the problem. The reduced code could look like this:
class Edge {
public:
int flow;
};
class Node {
private:
vector<Edge> adjNodeList; // list of outgoing edges for this vertex
public:
vector<Edge> & getAdjNodeList() {
return adjNodeList;
}
void addAdjNode(Node* newAdj) {
adjNodeList.push_back(Edge(newAdj));
}
};
int main() {
Node *node1 = new Node();
Node *node2 = new Node();
node1->addAdjNode(node2);
vector<Edge> t = node1->getAdjNodeList();
vector<Edge> f = node1->getAdjNodeList();
t[0].flow = 11;
cout << t[0] << endl;
cout << f[0] << endl;
}
If you would run this code, you would notice that t[0] and f[0] are not the same. As I just copied the crucial elements of your code, the reason should still be the same.
What is happening here? When calling
vector<Edge> t = node1->getAdjNodeList();
the adjacency list is returned by reference, which should leave you with a reference to the original list - you should be able to change it's elements, shouldn't you? However, when assigning this reference to the newly allocated vector t, the implicit copy constructor is called, thus t will contain a copy (!) of your vector while you wanted to save a reference.
To get around this problem, you could just have done the following:
vector<Edge> & t = node1->getAdjNodeList();
which saves the reference and does not create a new object.
I can only assume why the pointers happened to be identical between calls to the function: The object probably was copied to the same place every time. Furthermore, note that you increased the value of an object that did not exist anymore - the copy was deleted with the end of the find_edge-call.
It took some time to give an answer to your question as you did not track the problem down yourself. If you had given the example above, I bet your solution would have been there within a matter of minutes. You are encouraged to raise your problems here at stack overflow - however, most members will not be willing to work through a lot of code to identify the problem themselves. That means, high quality answers usually require questions that directly come to the point. (The last paragraph was intended to help you in the future, however, it could be reduced without altering the question).
Apart from that, I would strongly encourage you not to use your objects the way you do. By passing everything as references and making all changes outside the object, you essentially bypass the encapsulation that makes object orientated programming that powerful. For example, it would be much wiser (and would not have given you your problem) if you just had added another function increaseFlow(Edge* to, int increment) to your Node and had done everything within the object.
Hope I could help.
Related
I am trying implementing the huffman algorithm following the steps described in this tutorial: https://www.programiz.com/dsa/huffman-coding, and so far I got this code:
void encode(string filename) {
List<HuffmanNode> priorityQueue;
List<Node<HuffmanNode>> encodeList;
BinaryTree<HuffmanNode> toEncode;
//Map<char, string> encodeTable;
fstream input;
input.open(filename, ios_base::in);
if (input.is_open()) {
char c;
while (!input.eof()) {
input.get(c);
HuffmanNode node;
node.data = c;
node.frequency = 1;
int pos = priorityQueue.find(node);
if(pos) {
HuffmanNode value = priorityQueue.get(pos)->getData();
value++;
priorityQueue.update(pos, value);
} else {
priorityQueue.insert(node);
}
}
}
input.close();
priorityQueue.sort();
for(int i=1; i<=priorityQueue.size(); i++)
encodeList.insert( priorityQueue.get(i) );
while(encodeList.size() > 1) {
Node<HuffmanNode> * left = new Node<HuffmanNode>(encodeList.get(1)->getData());
Node<HuffmanNode> * right = new Node<HuffmanNode>(encodeList.get(2)->getData());
HuffmanNode z;
z.data = 0;
z.frequency = left->getData().frequency + right->getData().frequency;
Node<HuffmanNode> z_node;
z_node.setData(z);
z_node.setPrevious(left);
z_node.setNext(right);
encodeList.remove(1);
encodeList.remove(1);
encodeList.insert(z_node);
}
Node<HuffmanNode> node_root = encodeList.get(1)->getData();
toEncode.setRoot(&node_root);
}
full code for the main.cpp here: https://pastebin.com/Uw5g9s7j.
When I try run this, the program read the bytes from the file, group each character by frequency and order the list, but when I try generate the huffman tree, I am unable to traverse this tree, always falling into a infinte loop (the method get stuck in the nodes containing the 2 first items from the priorityQueue above).
I tried the tree class with BinaryTree<int>, and everything works fine in this case, but with the code above the issue happens. The code for the tree is this (in the code, previous == left and next == right - I am using here the same Node class already implemented for my List class): https://pastebin.com/ZKLjuBc8.
The code for the List used in this example is: https://pastebin.com/Dprh1Pfa. And the code for the Node class used for both the List and the BinaryTree classes is: https://pastebin.com/ATLvYyft. Anyone can tell me what I am missing here? What I am getting wrong here?
UPDATE
I have tried a version using only c++ stl (with no custom List or BinaryTree implementations),but the same problem happened. The code is that: https://pastebin.com/q0wrVYBB.
Too many things to mention as comments so I'm using an answer, sorry:
So going top to bottom through the code:
Why are you defining all methods outside the class? That just makes the code so much harder to read and is much more work to type.
Node::Node()
NULL is C code, use nullptr. And why not use member initialization in the class?
class Node {
private:
T data{};
Node * previous{nullptr};
Node * next{nullptr};
...
Node::Node(Node * node) {
What is that supposed to be? You create a new node, copy the value and attach it to the existing list of Nodes like a Remora.
Is this supposed to replace the old Node? Be a move constructor?
Node::Node(T data)
Write
Node<T>::Node(T data_ = T{}) : data{data_} { }
and remove the default constructor. The member initialization from (1) initializes the remaining members.
Node::Node(T data, Node * previous, Node * next)
Again creating a Remora. This is not inserting into an existing list.
T Node::getData(), void Node::setData(T value)
If everyone can get and set data then just make it public. That will also mean it will work with cons Node<T>. Your functions are not const correct because you lack all the const versions.
Same for previous and next. But those should actually do something when you set the member. The node you point to should point back to you or made to do so:
void Node::setPrevious(Node * previous) {
// don't break an existing list
assert(this->previous == nullptr);
assert(previous->next == nullptr);
this->previous = previous;
previous->next = this;
}
Think about the copy and move constructors and assignment.
Follow the rule of 0/3/5: https://en.cppreference.com/w/cpp/language/rule_of_three . This goes for Node, List, ... all the classes.
List::List()
Simpler to use
Node<T> * first{nullptr};
List::~List()
You are deleting the elements of the list front to back, each time traversing the list from front till you find index number i. While horrible inefficient the front nodes have also already been deleted. This is "use after free".
void List::insert(T data)
this->first = new Node<T>();
this->first->setData(data);
just write
first = new Node<T>(data);
And if insert will append to the tail of the list then why not keep track of the tail so the insert runs in O(1)?
void List::update(int index, T data)
If you need access to a list by index that is a clear sign that you are using the wrong data structure. Use a vector, not a list, if you need this.
void List::remove(int index)
As mentioned in comments there are 2 memory leaks here. Also aux->next->previous still points at the deleted aux likely causing "use after free" later on.
int List::size()
Nothing wrong here, that's a first. But if you need this frequently you could keep track of the size of the list in the List class.
Node * List::get(int index)
Nothing wrong except the place where you use this has already freed the nodes so this blows up. Missing the const counterpart. And again a strong indication you should be using a vector.
void List::set(int index, Node * value)
What's this supposed to do? Replace the n-th node in a list with a new node? Insert the node at a specific position? What it actually does it follow the list for index steps and then assign the local variable aux the value of value. Meaning it does absolutely nothing, slowly.
int List::find(T data)
Why return an index? Why not return a reference to the node? Also const and non-const version.
void List::sort()
This code looks like a bubblesort. Assuming it wasn't totaly broken by all the previous issues, would be O(n^4). I'm assuming the if(jMin != i) is supposed to swap the two elements in the list. Well, it's not.
I'm giving up now. This is all just the support classes to implement the BinaryTree, which itself is just support. 565 lines of code before you even start with your actual problem and it seems a lot of it broken one way or another. None of it can work with the state Node and List are in. Especially with copy construction / copy assignment of lists.
I'm trying to create a node class that contains a vector of pointers. Here's my code:
node.h:
#ifndef NODE_H
#define NODE_H
class node
{
public:
vector<node*> next;
void add_arc(node & a)
string some_string;
#endif
node.cpp:
void node::add_arc(node & a)
{
node *b = &a;
next.push_back(b); //only copyies nodes
}
main.cpp:
int main()
{
vector<node> nodes;
node a;
node b;
node c;
a.somestring = "a";
b.somestring = "b";
c.somestring = "c";
a.add_arc(b); //a should point to b
a.add_arc(c); //a should point to c
nodes.push_back(a);
nodes.push_back(b);
nodes.push_back(c);
cout << nodes[0].next.size() << endl; // prints "2", works fine
cout << nodes[0].next[0]->some_string << endl; //empty
}
I thought it would be as easy as just overloading push_back:
void push_back(vertex * pointer)
{
next.push_back(pointer);
}
But I think I really need a copy constructor, or some other method to make this work. How would I go about doing this for a vector of pointers?
Edit: I guess I didn't explain it well. Look at the answers in this question:
Segmentation fault when accessing a pointer's member function in a vector
Making 'a' a reference did not work for me
It works...
Your code generates as expected the correct output (see online demo):
2
b
...However this design is not future proof
However this result is related somehow to luck, because in your code snippet:
the nodes in the nodes vector are copies of the original object including all their pointers
the local objects a, b, c to which these pointers point still exist
However in more complex code, you'd quickly end up with dangling pointers.
Imagine:
Bad example 1: you create a graph, keeping all the nodes directly in a vector of nodes. You then add the first arcs between the nodes. As soon as you'll add a new node to the vector, reallocation might occur and you'd risk to see all your next pointers invalidated.
Bad example 2: you initialise a graph like you did, but in a function called by main. In this case, as soon as you return from this function, all the local nodes get destroyed and the vector's node will point to objects that do no longer exist. UB guaranteed !
How to improve ?
Your design fails to recognize that the nodes all belong to the same graph.
There is a quick and dirty way out: always create the node from the free store, and store them in a vector<node*>.
vector<node*> nodes;
node *a = new node("a"); // Imagine a node constructor
node *b = new node("b");
a->add_arc(b); //change signature, to accept a pointer
nodes.push_back(a);
nodes.push_back(b);
There's a better approach: improve further the previous approach, but use shared_ptr<node*> to make sure that nodes that are no longer referenced (neither by a vector of nodes, nor by an arc) are destroyed automatically.
There's an even better approach: encapsulate the nodes in a class representing a graph. In this case, you could consider using a vector<nodes> and replace the pointers in next, by indexes of the target nodes in the vector. No pointer, but perfect copy of graphs will be much easier. And no more memory management hassle.
class node // just to give the general idea
{
public:
vector<int> next; // not usable without the graph
void add_arc(int a)
string id;
};
class graph {
vector<node> nodes;
public:
void add_node (node a);
void add_arc (string from, string to);
node& operator[] (size_t i);
...
};
now i have been making games for a few years using the gm:s engine(tho i assure you i aint some newbie who uses drag and drop, as is all to often the case), and i have decided to start to learn to use c++ on its own, you know expand my knowledge and all that good stuff =D
while doing this, i have been attempting to make a list class as a practice project, you know, have a set of nodes linked together, then loop threw those nodes to get a value at a index, well here is my code, and i ask as the code has a single major issue that i struggle to understand
template<class type>
class ListNode
{
public:
type content;
ListNode<type>* next;
ListNode<type>* prev;
ListNode(type content) : content(content), next(NULL), prev(NULL) {}
protected:
private:
};
template<class type>
class List
{
public:
List() : SIZE(0), start(NULL), last(NULL) {}
unsigned int Add(type value)
{
if (this->SIZE == 0)
{
ListNode<type> a(value);
this->start = &a;
this->last = &a;
}
else
{
ListNode<type> a(value);
this->last->next = &a;
a.prev = this->last;
this->last = &a;
}
this->SIZE++;
return (this->SIZE - 1);
}
type Find(unsigned int pos)
{
ListNode<type>* a = this->start;
for(unsigned int i = 0; i<this->SIZE; i++)
{
if (i < pos)
{
a = a->next;
continue;
}
else
{
return (*a).content;
}
continue;
}
}
protected:
private:
unsigned int SIZE;
ListNode<type>* start;
ListNode<type>* last;
};
regardless, to me at least, this code looks fine, and it works in that i am able to create a new list without crashing, as well as being able to add elements to this list with it returning the proper index of those elements from within the list, however, beyond that the problem arises when getting the value of a element from the list itself, as when i ran the following test code, it didn't give me what it was built to give me
List<int> a;
unsigned int b = a.Add(313);
unsigned int c = a.Add(433);
print<unsigned int>(b);
print<int>(a.Find(b));
print<unsigned int>(c);
print<int>(a.Find(c));
now this code i expected to give me
0
313
1
433
as that's what is been told to do, however, it only half does this, giving me
0
2686684
1
2686584
now, this i am at a lost, i assume that the values provided are some kind of pointer address, but i simply don't understand what those are meant to be for, or what is causing the value to become that, or why
hence i ask the internet, wtf is causing these values to be given, as i am quite confused at this point
my apologies if that was a tad long and rambling, i tend to write such things often =D
thanks =D
You have lots of undefined behaviors in your code, when you store pointers to local variables and later dereference those pointers. Local variables are destructed once the scope they were declared in ends.
Example:
if (this->SIZE == 0)
{
ListNode<type> a(value);
this->start = &a;
this->last = &a;
}
Once the closing brace is reached the scope of the if body ends, and the variable a is destructed. The pointer to this variable is now a so called stray pointer and using it in any way will lead to undefined behavior.
The solution is to allocate the objects dynamically using new:
auto* a = new ListNode<type>(value);
Or if you don't have a C++11 capable compiler
ListNode<type>* a = new ListNode<type>(value);
First suggestion: use valgrind or a similar memory checker to execute this program. You will probably find there are many memory errors caused by dereferencing stack pointers that are out of scope.
Second suggestion: learn about the difference between objects on the stack and objects on the heap. (Hint: you want to use heap objects here.)
Third suggestion: learn about the concept of "ownership" of pointers. Usually you want to be very clear which pointer variable should be used to delete an object. The best way to do this is to use the std::unique_ptr smart pointer. For example, you could decide that each ListNode is owned by its predecessor:
std::unique_ptr<ListNode<type>> next;
ListNode<type>* prev;
and that the List container owns the head node of the list
std::unique_ptr<ListNode<type>> start;
ListNode<type>* last;
This way the compiler will do a lot of your work for you at compile-time, and you wont have to depend so much on using valgrind at runtime.
I am trying to create a maze that consists of Nodes objects. Each Node object has a member variable Node *attachedNodes[4] that essentially contains all of the attached Nodes that will later tell the program the options it has when it is doing a breadth first search. Every time I think that I understand pointers, another issue like this comes up, and I feel lost all over again. Especially since it was working fine (as far as I knew) until I changed something that I thought was unrelated. Anyways, here is where the issues are:
My Node object looks like this
class Node {
public:
...
void attachNewNode(Node *newNode, int index);
...
private:
...
Node *attachedNodes[4];
...
};
My function to attach the Nodes looks like this:
void Node::attachNewNode(Node *newNode, int index) {
*attachedNodes[index] = *newNode;
}
And then lastly, the part of the other function that is calling the attachNewNode function looks like this:
int mazeIndex = 0;
while (inStream.peek() != EOF) {
int count = 0;
Node n;
Node m;
...
if (System::isNode(name2)) {
m = System::findNode(name2);
}
else {
m = Node(name2);
maze[mazeIndex] = m;
mazeIndex++;
}
Node *temp;
*temp = m;
n.attachNewNode(temp, count); //The error usually happens here, but I added the rest of the code because through debugging it is only consistently in this whole area.
count++;
}
n.setNumberUsed(count);
}
Sorry that this got a little lengthy, but I've been searching all over this portion that I have provided trying to figure out what is wrong, but it would be nice to have someone that knows a little more about pointers give their input on the matter. The Node class was given to me, but everything else I made, so basically any of that could be changed. Thanks in advance for the help.
Your class contains a property:
Node *attachedNodes[4];
The above says that attachedNodes is an array that contains 4 pointers to Nodes. In your attachNewNode function, you do:
*attachedNodes[index] = *newNode;
This means that you are trying to assign value of newNode (as * dereferences the pointer) to the value of the element under attachedNodes[index]. What you probably want is:
attachedNodes[index] = newNode;
This means that you just want to store the address (as pointer is just an address to some place in memory) in the array of addresses.
There is also another error here:
Node *temp;
*temp = m;
n.attachNewNode(temp, count);
Again, you are interested in storing the address of node m. In order to do that, you need to get the said address:
Node *temp;
temp = &m;
n.attachNewNode(temp, count);
These are the most obvious problems with the above code, but there might be more.
I am trying to use the C++ "Clipper Library" (http://www.angusj.com/delphi/clipper.php), but when I try to return one of the objects from the clipper library from a function, it seems to become null or is altered somehow
Here is the function I wrote. The only relevant lines should be the last 3.
ClipperLib::PolyTree MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles)
{
// Make all of the triangles CW
for (auto& triangle : triangles)
{
triangle.makeClockwise();
}
// Set up the Clipper
ClipperLib::Clipper clipper;
// To take a union, add all the paths as "subject" paths
for (auto& triangle : triangles)
{
ClipperLib::Path triContour(3);
triContour[0] = convertGLMToClipperPoint(triangle.getVertex(0));
triContour[1] = convertGLMToClipperPoint(triangle.getVertex(1));
triContour[2] = convertGLMToClipperPoint(triangle.getVertex(2));
clipper.AddPath(triContour, ClipperLib::PolyType::ptSubject, true);
}
// Now get the PolyTree representing the contours
ClipperLib::PolyTree tree;
clipper.Execute(ClipperLib::ClipType::ctUnion, tree);
return tree;
}
When I call clipper.execute, it writes into the tree structure some contour information. It writes the correct information, and I've tested that it's correct. However, when I return the tree, it doesn't seem to copy anything, and the PolyTree that results from this function is empty.
I'm sure that there's nothing wrong with the library and that I'm just making a beginner c++ mistake here. Hopefully someone has an idea of what it might be.
Thanks!
edit: For reference, here is a documentation page for the polytree (http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/PolyTree/_Body.htm)
edit: I thought the clipper library wasn't open source, but it is. Here is the code
typedef std::vector< IntPoint > Path;
typedef std::vector< Path > Paths;
class PolyNode;
typedef std::vector< PolyNode* > PolyNodes;
class PolyNode
{
public:
PolyNode();
Path Contour;
PolyNodes Childs;
PolyNode* Parent;
PolyNode* GetNext() const;
bool IsHole() const;
bool IsOpen() const;
int ChildCount() const;
private:
unsigned Index; //node index in Parent.Childs
bool m_IsOpen;
JoinType m_jointype;
EndType m_endtype;
PolyNode* GetNextSiblingUp() const;
void AddChild(PolyNode& child);
friend class Clipper; //to access Index
friend class ClipperOffset;
};
class PolyTree: public PolyNode
{
public:
~PolyTree(){Clear();};
PolyNode* GetFirst() const;
void Clear();
int Total() const;
private:
PolyNodes AllNodes;
friend class Clipper; //to access AllNodes
};
Before doing anything, make sure the following program works correctly:
int main()
{
PolyTree p1;
// fill PolyTree with some values that make sense (please add code to do this)
//...
PolyTree p2 = p1;
PolyTree p3;
p3 = p1;
}
That is basically what we want to test. If you can get this code to work (add the relevant headers and initializations necessary), then you can focus back on the function. If the code above doesn't work, then there is your answer.
You need to get the code above to produce the correct copy semantics, and even just important, when main() exits, no memory corruption occurs on the destruction of p1, p2, and p3.
So either you can fix the class to copy safely, or forget about it and live with a class that you have to handle very carefully and in limited situations (i.e. you can't reliably return copies of it as you're doing now).
For the record and combining all the responses in the lengthy discussion to the question.
Problems are:
The value returned is a local variable that goes out of scope. This invokes the PolyTree destructor
The PolyTree contains a vector of PolyNode * pointers. Those are allocated when clipper.Execute() is invoked.
However PolyTree::Clear() does delete the nodes... and Clear() is invoked by the destructor.
So within the function, the content is correct (allocated by Execute()), when passed outside, in the absence of copy constructors and operator=, the destructor of the local variable is invoked an the nodes are cleared, the result received outside of the function is empty.
The code for PolyTree::Clear()
void PolyTree::Clear()
{
for (PolyNodes::size_type i = 0; i < AllNodes.size(); ++i)
delete AllNodes[i];
AllNodes.resize(0);
Childs.resize(0);
}
Probably you should follow the pattern of Execute and define your function as:
void MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles,ClipperLib::PolyTree &tree)
Assuming you don't want to modify the (obviously badly designed) Clipper library, you can do it like I suggested in my comment:
// Make sure to have this at the top of your header file:
#include <memory>
std::unique_ptr<ClipperLib::PolyTree> MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles)
{
// Rest of your code...
std::unique_ptr<ClipperLib::PolyTree> tree(new ClipperLib::PolyTree);
clipper.Execute(ClipperLib::ClipType::ctUnion, *tree);
return tree;
}
Then, when calling your function:
std::unique_ptr<ClipperLib::PolyTree> tree(yourMeshHandler.trianglesToPolyTreeUnion(/*...*/);
// make use of tree...
Still, I would suggest opening a ticket (if there's a bug tracker) or contacting the library's author about this issue.
Is there already a solution for this problem? I am dealing with the same problem.
Still no luck. The polytree outputs only memory adres.
when using : qDebug()<< "child id " << polynode->Childs;
When we have 2 childs, the output in terminal is :
std::vector(0x55f30d2a91b0, 0x55f30d258480)
I hope someone knows how to solve this..
Your problem is in the third line from the bottom of trianglesToPolyTreeUnion. The tree you are creating is created on the stack and is only in scope within the function.
You should dynamically allocate the memory and return a pointer to the tree or make your tree object a class member so it is still within scope once the function returns.