Display() resets the entire array C++ - c++

I tried creating a hash map storing its inputs as linked list nodes using separated chaining. The first display function gives a desirable output, but the next one resets the entire array to empty nullptr. I used the same class object so shouldn't it give the same result each time? Was it because of the destructor somehow? I thought it may be because I inserted a new item so I deleted it and the same thing still persists. My only suspect is the display() function but please point out if the problem comes from somewhere else.
Sorry if the post is so long, I want to make sure everyone can see the entire code to spot the problem.
#include <iostream>
#include <string>
#include "C:\Users\admin\source\repos\hash-library-master\sha3.cpp"
using namespace std;
const int TABLE_SIZE = 11;
struct HashNode
{
string key;
string value;
HashNode* next;
};
class HashMap {
private:
HashNode **table;
public:
//each element of table will be a root pointer to their respective chain
HashMap() {
table = new HashNode*[TABLE_SIZE];
for (int i = 0; i < TABLE_SIZE; i++)
{
table[i] = nullptr;
}
}
//hashing algorithm using SHA3 (courtesy of Stephan Brumme)
string hashFunc(string input)
{
string key;
SHA3 sha3;
key = sha3(input);
return key;
}
//insert new node
void insert(string key, string value)
{
//using hashing function to calculate hash index from string variable key
int hash = 0;
for (int a = 0; a < key.length(); ++a)
hash += key[a];
hash = hash % TABLE_SIZE;
//create new node to store data
HashNode* newNode = new HashNode;
newNode->value = value;
newNode->key = key;
newNode->next = nullptr;
//check and insert new node to front of line
if (table[hash] == nullptr)
table[hash] = newNode;
else
{
newNode->next = table[hash]->next;
table[hash]->next = newNode;
}
}
void display()
{
for (int i = 0; i < TABLE_SIZE; ++i)
{
if (table[i] == nullptr)
cout << i << " NULL" << endl;
else
{
while (table[i] != nullptr)
{
cout << i << " " << table[i]->value << "; ";
table[i] = table[i]->next;
if (table[i] == nullptr)
cout << "(end of chain)" << endl;
}
}
}
}
~HashMap() {
for (int i = 0; i < TABLE_SIZE; i++)
if (table[i] != NULL)
delete table[i];
delete[] table;
}
};
Driver
#include <iostream>
#include <string>
#include "hashMap.h"
using namespace std;
int main()
{
HashMap obj;
//test insert
obj.insert("5", "3100 Main St, Houston TX ");
obj.insert("5", "2200 Hayes Rd, Austin TX");
obj.insert("226", "1775 West Airport St, San Antonio TX");
obj.insert("273", "3322 Walnut Bend, Houston TX");
obj.insert("491", "5778 Alabama, Waco TX");
obj.insert("94", "3333 New St, Paris TX");
obj.display(); //resolved
cout << endl << endl;
//testing new hashing algorithm
string input, key;
cout << "Please enter any new address you want to store: ";
cin >> input;
key = obj.hashFunc(input); //create hash key
obj.insert(key, input);
obj.display(); //resets the array somehow
return 0;
}
Output
0 1775 West Airport St, San Antonio TX; (end of chain)
1 NULL
2 3322 Walnut Bend, Houston TX; (end of chain)
3 NULL
4 5778 Alabama, Waco TX; (end of chain)
5 NULL
6 NULL
7 NULL
8 NULL
9 3100 Main St, Houston TX ; 9 2200 Hayes Rd, Austin TX; (end of chain)
10 3333 New St, Paris TX; (end of chain)
//where display() resets
Please enter any new address you want to store: ewrewrw
0 NULL
1 ewrewrw; (end of chain)
2 NULL
3 NULL
4 NULL
5 NULL
6 NULL
7 NULL
8 NULL
9 NULL
10 NULL

Make all member functions that are not supposed to change the object itself const. This ensures that the function can be used when the object is used in a const context and will also enable the compiler to help you if you make a mistake. It will give you compilation errors if you try modifying the object in the function and will therefore complain about the line table[i] = table[i]->next; where you make changes to the object in your current code.
So start by making the function const and fix the errors. With the fixes in place it could look something like this:
void display() const // const added
{
for (int i = 0; i < TABLE_SIZE; ++i)
{
if (table[i] == nullptr)
cout << i << " NULL" << endl;
else
{
// using a temporary pointer, ptr, to go through the list
for(HashNode* ptr = table[i]; ptr != nullptr; ptr = ptr->next)
{
cout << i << " " << ptr->value << "; ";
}
cout << "(end of chain)" << endl;
}
}
}

Your display function is setting all elements of table to nullptr by looping until they become nullptr.
You should use another pointer variable for iterating to avoid this destruction.
void display()
{
for (int i = 0; i < TABLE_SIZE; ++i)
{
if (table[i] == nullptr)
cout << i << " NULL" << endl;
else
{
HashNode *p = table[i]; // another pointer variable for iterating
while (p != nullptr)
{
cout << i << " " << p->value << "; ";
p = p->next;
if (p == nullptr)
cout << "(end of chain)" << endl;
}
}
}
}

Related

if user enter 5 then display the last 5 elements of linked list vise versa

i am stuck in my uni assignment....
i have an linked list of 20 elements, i have to take the value from user and if user enter 5 then print the last 5 elements of linked list
void traverse(List list) {
Node *savedCurrentNode = list.currentNode;
list.currentNode = list.headNode;
for(int i = 1; list.next() == true; i++)
{
std::cout << "Element " << i << " " << list.get() << endl;
}
list.currentNode = savedCurrentNode;
}
im trying this but this method prints all the elements of my linked list
For what little code you have, a review:
// Why are you passing the list by value? That is wasteful.
void traverse(List list) {
// I don't see you taking a value anywhere; surely you know how to do that
// What is happening here? Can't you just assign the head to something
// directly?
Node *savedCurrentNode = list.currentNode;
list.currentNode = list.headNode;
// Like you said, this traverses the entire list, it's also poorly
// formed. You literally don't need i.
// for (; list.next(); /* However your list increments here */)
for(int i = 1; list.next() == true; i++)
{
std::cout << "Element " << i << " " << list.get() << endl;
}
// What is the purpose of this?
list.currentNode = savedCurrentNode;
}
For someone who is writing a linked list, this code seems to be fundamentally flawed. My expectation of someone tackling a linked list is that they are about to stop being a beginner, but I'm not seeing that here in the code and what structure of the list class is implied. The list class is weird to say the least.
And just to be clear, my expectation stems from where I place the linked list assignment in my curriculum. It's also more idiomatic than this list.
With that out of the way, this task is trivial if you took the time to think the project through. Most students skip the planning step and create unnecessary headaches for themselves.
Knowing that you would need the total size of the list, why not just make it member data? Any function that adds to the list will increment the value accordingly. And any function that subtracts from the list will decrement accordingly. That way you always know the size of the list at all times.
Knowing the size of the list is most of the battle. You then need to do the arithmetic necessary to advance in the list to satisfy your requirement. And now you can print.
#include <iostream>
class SList {
public:
SList() = default;
//
// Rule of 5 intentionally left out
//
void push_front(int val) {
m_head = new Node{val, m_head};
++m_size; // The magic happens here
}
std::size_t size() const { return m_size; }
void traverse_last(int numElements, std::ostream& sout = std::cout) const {
int placement = m_size;
Node* walker = m_head;
// Move our walker node the appropriate amount of steps
while (walker && placement > numElements) {
walker = walker->next;
--placement;
}
// Now that we're in position, we can print
while (walker) {
sout << walker->data << ' ';
walker = walker->next;
}
sout << '\n';
}
private:
struct Node {
int data;
Node* next = nullptr;
};
Node* m_head = nullptr;
std::size_t m_size = 0ULL;
};
int main() {
SList test;
for (int i = 5; i > 0; --i) {
test.push_front(i);
}
std::cout << "Size: " << test.size() << '\n';
for (int i = 1; i <= 5; ++i) {
test.traverse_last(i);
}
test.traverse_last(10);
}
Output:
❯ ./a.out
Size: 5
5
4 5
3 4 5
2 3 4 5
1 2 3 4 5
1 2 3 4 5
void traverse(List list, int printFrom)
{
Node *savedCurrentNode = list.currentNode;
list.currentNode = list.headNode;
for(int i=1; list.next(); i++)
{
if(i > printFrom)
{
cout << "Element " << (i - printFrom) << " " << list.get() << endl;
}
}
list.currentNode = savedCurrentNode;
}
solved my prblem by this there printFrom is a variable whose value is number of elemenets that skipped like if my linked list have size of 20 and user want to see last 5 then printFrom stores 15 and skipped 15 values and print last 5

C++ access an element of struct array in a struct

This thing has been driving me crazy for a while now.
I need to create and traverse (post order) a general tree where each node (a structure) is added by the user via console.
I am NOT allowed to use STL.
The user specifies how many nodes will be added, and how many 'child' nodes it can hold (number) and the name of the node (string).
Example input:
5
1 A
2 B
1 C
1 D
3 E
The above means that 5 nodes will be added. The first one (A) can accept one 'child' node, (B) can accept 2 such nodes and (C) can accept 1 etc.
The newly added nodes have to always be added to the 'highest' possible node from the top (if it still can accept a new 'child' node, if not possible you go to the next one).
The idea is to create an array (I know how many nodes will be added in total) and put those nodes specified by the user there and 'link' them accordingly using array of pointers inside of a structure.
The output of given example should be: E C D B A
I have written the whole thing as follows but I am unable to traverse the tree:
structure:
struct node {
string name = "";
int noChildrenAdded = 0;
int possibleNoChildren = 0;
int childrenFreeSlots = 0;
node* children = nullptr;
node* father = nullptr;
};
traverse function that's not working
void traverse(node* father)
{
cout << father->name << endl;
if (father == nullptr) {
return;
}
for (int i = 0; i < father->possibleNoChildren; i++) {
if (&father->children[i] == nullptr) {
continue;
}
traverse(&father->children[i]);
}
cout << father->name << "\n";
}
main
int main() {
int n = 0;
short g = 0;
string name;
cin >> n;
node* tree = new node[n];
node* tmp = nullptr;
//adding children to tree array
for (int i = 0; i < n; i++) {
cin >> g >> name;
tree[i].possibleNoChildren = tree[i].childrenFreeSlots = g;
tree[i].name = name;
tree[i].noChildrenAdded = 0;
tree[i].children = new node[1];
}
// making connections between nodes
for (int son = 1; son < n; son++) {
for (int father = 0; father < son; father++) {
if (tree[father].childrenFreeSlots > 0) {
//resizing array
if (tree[father].noChildrenAdded == 0) {
tree[father].children[0] = tree[son];
}
else {
int added = tree[father].noChildrenAdded;
tmp = new node[added + 1];
for (int i = 0; i < added; i++) {
tmp[i] = tree[father].children[i];
}
delete[] tree[father].children;
tree[father].children = nullptr;
tree[father].children = tmp;
tree[father].children[added] = tree[son];
tmp = nullptr;
}
tree[father].noChildrenAdded++;
tree[father].childrenFreeSlots -= 1;
break;
}
}
}
//this is how it should be
cout << "Father: " << tree[1].name << "\tchildren added: " << tree[1].noChildrenAdded << endl;
//tree[0].children[0] is holding pointer to drzewo[1] so the below should give me the same answer as above.
//this is giving me wrong answer
node* ptr = &tree[0].children[0];
cout << "Father: " << ptr->name << "\tchildren added: " << ptr->noChildrenAdded << endl;
//traverse(&tree[0]);
delete[] tree;
}
THE PROBLEMS
I am unable to access details of a structure (for example noChildrenAdded) - I am getting zero, despite the fact that noChildrenAdded is populated. When I access it via tree array I am getting the correct number but when I do it via pointer inside of a struct I am getting 0.
Example:
This is correct: cout << "Father: " << tree[1].name << "\tchildren added: " << tree[1].noChildrenAdded << endl;
But this is not (despite both should be giving the same number/answer):
//tree[0].children[0] is holding pointer to tree[1] so the below should give me the same answer as above.
//this is giving me wrong answer
node* ptr = &tree[0].children[0];
cout << "Father: " << ptr->name << "\tchildren added: " << ptr->noChildrenAdded << endl;
I expect I have messed up assigning children to the *children array inside of a struct. The name seems to be accessible fine but not the noChildren.
Both should be giving the same answer but they are not:
enter image description here
Any help would be greatly appreciated!
PS: when I use this code with static array of children everything is ok, traversal works fine but when I get a dynamic array it's broken. Static array alas won't do as it taking too much memory and takes way too long so my program fails the requirements.
Just as #igor-tandetnik suggested, using an array of node* pointers solved the problem. In my case solution was to use node** children not node *children.

How can I traverse a Huffman Tree (via code) and print out the encodings for each letter?

I'd like to start with what I know about heaps and Huffman code.
For this project, we use a minimum heap. The top part of the upside-down tree (or root) holds the minimum element. Whenever something is added to the array, everything gets moved, so the root is always the minimum value element. Whenever an element is deleted, everything gets reconfigured with the top element holding the minimum once again. In class, we went over a (template) class called MaxHeap, which I converted into MinHeap without the template stuff.
My professor went over Huffman encoding, but I understood it best using this visual tool:
https://people.ok.ubc.ca/ylucet/DS/Huffman.html
The idea is to use a minimum heap as follows:
1. Delete two nodes
2. Create a new node with the deleted nodes as children. The frequency of this node is the summation of the two children frequencies.
3. Add this new node to the minimum heap
This process repeats until there is one node left in the heap (the root). Next, we find the encodings for each letter. To do this, travel down the tree with left movement being 0 and right movement being 1. Traveling right twice then left once would give 110 for the letter 'c' in my tree (image link can be found towards the bottom of my post).
Everything was going mostly fine until I needed to traverse from the root. I had no idea how to do this via code, so I tried googling the answers and found these two websites:
https://www.geeksforgeeks.org/huffman-coding-greedy-algo-3/
https://www.programiz.com/dsa/huffman-coding
I copied their function printCodes() into my code, but I didn't get see it work.
When I try manually going down the tree, I get two things. For example, I tried traveling left down the root and using cout to see the values. I expected to see 40, !, e, d; but when I tried I was getting gibberish number and characters (greek letters like theta, sigma, etc). It gets really weird because on line 207, yourRoot->left->freq gives me 40, but the same thing on the line 208 of code gives me a large number. When I traveled right, I got: Exception thrown: read access violation. yourRoot->right->right->letter was 0xCCCCCCCC.
To reiterate cout << yourRoot->left->freq << endl; will give me 40 the first time I call it, but the second time I get a random number. I expected the same output twice in a row. Am I supposed to keep a pointer or pointer-to-pointer to the address of yourRoot or something?
Another problem is in createHuffmanTree(), if I put return root; outside the while loop I get this error and the code doesn't run at all:
potentially uninitialized local pointer variable 'root' used
Both of these things were odd problems and I assume it has to do with the way I'm using & and * symbols. I tried using something like this:
MinHeap yourHeap = MinHeap(6);
node *item = newNode(30, 'f');
yourHeap.Insert(*item);
item = newNode(20, 'e');
yourHeap.Insert(*item);
item = newNode(20, 'd');
yourHeap.Insert(*item);
item = newNode(15, 'c');
yourHeap.Insert(*item);
item = newNode(10, 'b');
yourHeap.Insert(*item);
item = newNode(5, 'a');
yourHeap.Insert(*item);
delete item;
This works the same as the yourList[] code I have in main(), but I figured "keep it simple stupid" and avoid using pointers since I clearly have some issues with them.
I uploaded an output without any error causing code and a drawing of what I expect my tree to look like with the values I want to use (https://imgur.com/a/Vpx7Eif). If the link doesn't work, please let me know so I can fix it.
The code I have thus far is:
#include <iostream>
using namespace std;
#define MAX_TREE_HEIGHT 20
//exception is thrown if wrong input
class NoMem
{
public:
NoMem() { cout << "Heap is full\n"; }
};
class OutOfBounds
{
public:
OutOfBounds() { cout << "Heap is empty\n"; }
};
struct node
{
int freq;
char letter;
struct node *left, *right;
};
// initialize node with frequency and letter
node* newNode(int freq, char letter)
{
node *temp = new node;
temp->freq = freq;
temp->letter = letter;
temp->left = nullptr;
temp->right = nullptr;
return temp;
}
// initialize node using two nodes as children
node* newNode(node& a, node& b)
{
node *temp = new node;
temp->freq = a.freq + b.freq;
temp->letter = '!';
temp->left = &a;
temp->right = &b;
return temp;
}
class MinHeap {
public:
MinHeap(int MSize)
{
MaxSize = MSize;
heap = new node[MaxSize + 1];
Size = 0;
}
~MinHeap() { delete[] heap; }
MinHeap& Insert(node& x);
MinHeap& Delete(node& x);
void Display();
int Size;
private:
int MaxSize;
node *heap;
};
MinHeap& MinHeap::Insert(node& x)
{
if (Size == MaxSize) throw NoMem();
else
{
printf("Inserting '%c' with frequency of %d. ", x.letter, x.freq);
int i = ++Size;
while (i != 1 && x.freq < heap[i / 2].freq)
{
heap[i] = heap[i / 2];
i /= 2;
}
heap[i] = x;
Display();
return *this;
}
}
MinHeap& MinHeap::Delete(node& x)
{
if (Size == 0) throw OutOfBounds();
x.freq = heap[1].freq; // root has the smallest key
x.letter = heap[1].letter;
printf("Deleting '%c' with frequency of %d. ", x.letter, x.freq);
node y = heap[Size--]; // last element
int vacant = 1;
int child = 2; //make child = left child
while (child <= Size)
{
if (child < Size && heap[child].freq > heap[child + 1].freq) ++child;
// right child < left child
if (y.freq <= heap[child].freq) break;
heap[vacant] = heap[child]; // move smaller child
vacant = child; // new vacant
child = child * 2; // new child of vacant
}
heap[vacant] = y;
Display();
return *this;
}
void MinHeap::Display()
{
printf("Your heap contains: ");
for (int i = 1; i <= Size; i++)
printf("'%c' = %d, ", heap[i].letter, heap[i].freq);
printf("\n");
}
node* createHuffmanTree(MinHeap& yourHeap)
{
cout << "--- Creating Huffman Tree ---\n";
node left, right, *root;
while (yourHeap.Size > 1)
{
yourHeap.Delete(left);
yourHeap.Delete(right);
root = newNode(left, right);
cout << "-> New Node: freq = " << root->freq << ", letter = " << root->letter << ", left: " << root->left->letter << ", right: " << root->right->letter << endl;
yourHeap.Insert(*root);
if (yourHeap.Size < 2)
{
return root;
}
}
//return root; // potentially uninitialized local pointer variable 'root' used
}
void outputHuffmanCode(node* root, int arr[], int top)
{
// left movement is 0
if (root->left)
{
arr[top] = 0;
outputHuffmanCode(root->left, arr, top + 1);
}
// right movement is 1
if (root->right)
{
arr[top] = 1;
outputHuffmanCode(root->right, arr, top + 1);
}
// if reached leaf node, must print character as well
if (!(root->left) && !(root->right))
{
cout << "'" << root->letter << "' = ";
for (int i = 0; i < top; ++i)
cout << arr[i];
cout << endl;
}
}
int main()
{
node yourList[6];
yourList[0].freq = 5;
yourList[0].letter = 'a';
yourList[1].freq = 10;
yourList[1].letter = 'b';
yourList[2].freq = 15;
yourList[2].letter = 'c';
yourList[3].freq = 20;
yourList[3].letter = 'd';
yourList[4].freq = 20;
yourList[4].letter = 'e';
yourList[5].freq = 30;
yourList[5].letter = 'f';
cout << "Here is your list: ";
for (int i = 0; i < 6; i++)
{
cout << "'" << yourList[i].letter << "' = " << yourList[i].freq;
if (i < 5) cout << ", ";
} cout << endl;
MinHeap yourHeap(6);
yourHeap.Insert(yourList[5]);
yourHeap.Insert(yourList[4]);
yourHeap.Insert(yourList[3]);
yourHeap.Insert(yourList[2]);
yourHeap.Insert(yourList[1]);
yourHeap.Insert(yourList[0]);
/*
MinHeap yourHeap = MinHeap(6);
node *item = newNode(30, 'f');
yourHeap.Insert(*item);
item = newNode(20, 'e');
yourHeap.Insert(*item);
item = newNode(20, 'd');
yourHeap.Insert(*item);
item = newNode(15, 'c');
yourHeap.Insert(*item);
item = newNode(10, 'b');
yourHeap.Insert(*item);
item = newNode(5, 'a');
yourHeap.Insert(*item);
delete item;
*/
node *yourRoot = newNode(0, NULL);
yourRoot = createHuffmanTree(yourHeap);
// same cout twice in a row, different results
//cout << yourRoot->left->freq << endl;
//cout << yourRoot->left->freq << endl;
cout << "L0 Root: freq = " << yourRoot->freq << ", letter = " << yourRoot->letter << ", left freq: " << yourRoot->left->freq << ", right freq: " << yourRoot->right->freq << endl;
cout << "L11 Left: freq = " << yourRoot->left->freq << ", letter = " << yourRoot->left->letter << ", left: " << yourRoot->left->left->letter << ", right: " << yourRoot->left->right->letter << endl;
//cout << "R11 Left: freq = " << yourRoot->right->freq << ", letter = " << yourRoot->right->letter << ", left: \n";
//<< yourRoot->right->left->letter << ", right: " << yourRoot->right->right->letter << endl;
//int arr[MAX_TREE_HEIGHT], top = 0;
//outputHuffmanCode(yourRoot, arr, top);
system("pause");
return 0;
}
I'd like to thank whoever reads and replies to this post in advance. I think I've given as much information as I could. If I did anything that's against community rules, please let me know so I can fix my mistake(s).
In your createHuffmanTree Function, you create the node's left and right...
with root = newNode(left, right); you let the left/right member of your struct point to the address of the (temporary) node you've created in createHuffmanTree (that means in
node* newNode(node& a, node& b)
the address of a and b is always the same..
and the node goes out of scope after leaving the createHuffmanTree function - i think this causes your problem. You know what I mean?

Program Terminates unexpectedly C++

The goal of the program is to simulate a medical complex with 6 "Doctor Queues". I tried keeping it close enough to the Java version I've completed (must do this in 3 languages). At this point when I run the DequeuePatients and ListPatients method, the program terminates unexpectedly with no errors. I've tried the debugger but eclipse is ignoring all my breakpoints.Why is it terminating?
The ListPatients method is all follows in Driver class:
void ListPatients() {
int x, QueueChoice = 0;
bool exit = false;``
while (!exit) {
for (x = 1; x <= MAX; x++) {
cout << x << ": " << Doctor[x - 1] << "\n";
} // end-for
cout << "Choose a Queue to List From";
cin >> QueueChoice;
if (OpenFlag[QueueChoice - 1] == true) { //open flag for each queue
int i = Complex[QueueChoice - 1]->GetSize();//Global array of queues
//cout <<i<<endl;
Terminates in this loop if function is called
for (x = 1; x <= i; x++) {
Patient This = Complex[QueueChoice-1]->GetInfo(x); //Program Terminates here
cout << x<< ": " << endl;//This.ID_Number;
//<<Complex[QueueChoice - 1]->GetInfo(x + 1).PrintMe()
} // end-for
} // end-if
cout << "Press 1 to List Another Queue, press 2 to exit";
cin >> x;
switch (x) {
case 1:
break;
case 2:
exit = true;
break;
}//switch
} // end-while
} // List Patients`
Queue Class GetInfo and toArray():
/*Return Patient info from each Node*/
Patient Queue::GetInfo(int Pos) {
Node* ComplexArray= new Node[Length];
ComplexArray = this->toArray();
return ComplexArray[Pos - 1].Info;
}
// The toArray method
Node* Queue::toArray() {
// Copy the information in each node to an array and return the array.
int x = Length;
Node ComplexArray[Length] ={} ;
Node* Current = new Node();
Current = Rear;`
for (x = 0; x<Length;x++) {
ComplexArray[x] = Node();
ComplexArray[x].Modify(Current);
Current = Current->Next;
}
return ComplexArray;
} // End of toArray method
Modify Method in Node:
void Node :: Modify(Node* ThisNode)
{
Info = ThisNode->Info;
Next = ThisNode->Next;
}
If this is base-zero why are you subtracting 1 from x
for (x = 0; x<Length;x++) {
ComplexArray[x-1] = Node();
ComplexArray[x - 1].Modify(Current);
Current = Current->Next;
}
Subscript errors are hard crashes in C/C++.
The problem was sort of basic, it was way I was declaring my pointers, as well as changing the toArray function to return a Patient pointer(That can be treated as an array?) as apposed to Node, and not just to the first element of the array.
this caused toArray to return one Node pointer, with that instances Next pointer continuously pointing to itself.
Queue Complex[6] = Queue(); //in driver class
Patient* ComplexArray[Length] = new Patient();//Queue Class GetInfo & toArray
I needed:
Queue* Complex = new Queue[MAX];
Patient* ComplexArray = new Patient[Length];
and changed these functions:
Patient Queue::GetInfo(int Pos) {
Patient* ComplexArray = new Patient[Length];
ComplexArray= toArray();
return ComplexArray[Pos - 1];
}
// Now returns Patient pointer of Node->Info to GetInfo
Patient* Queue::toArray() {
Node* Current;
int x;
Patient* ComplexArray = new Patient[Length];
Current = Rear;
for (x = 1; x <= Length; x++) {
ComplexArray[x-1] = Patient();
ComplexArray[x - 1].Modify(Current->Info);
Current = Current->Next;
}
return ComplexArray;
} // End of toArray method

Pouring via Depth First Search node linking to itself. C++

Working on a program to solve the pouring problem:
I believe I am down to one last issue. My data structure is as follows:
I have an vector of Node pointers and each node contains a int array, and an address to the next node. In testing everything functions properly. The goal of this data structure is to basically function as an adjacency list. Where each node is linked to the nodes that it would have an edge to.
Currently my problem is when I am attempting to link these nodes to one another:
the LinkState function that I have should accomplish this, however it is instead resulting in the program running...forever.
The function should simply iterate through the individual nodes linked list and find where to connect the new node. Instead it is causing a node to constantly be leak to itself..which is leading to the runtime issue.
Sorry if this is a bit confusing. Any help would be greatly appreciated.
p.s. I know there are better ways to solve this problem like BFS, I'd like to stick to DFS.
#ifndef _POURINGLIST_H_
#define _POURINGLIST_H_
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
struct Node{
int state[3];
Node* next = NULL;
};
class PouringList{
Node* init;
vector<Node*> Head;
int max[3];
int steps;
public:
PouringList(){
//max values for comaprison
max[0] = 10;
max[1] = 7;
max[2] = 4;
//init values to begin DFS
init = new Node;
init->state[0] = 0;
init->state[1] = 7;
init->state[2] = 4;
};
//private methods not to be called by user
private:
//pours some good old h2o
Node pour(Node* curr_state, int A, int B){
int a = curr_state->state[A];
int b = curr_state->state[B];
int change = min(a, max[B]-b);
Node newState = *curr_state;
newState.state[A] = (a-=change);
newState.state[B] = (b+=change);
return newState;
}
//O(n) complexity used to check if a node is already in head
bool isIn(Node* find_me){
for(vector<Node*>::iterator i = Head.begin(); i != Head.end(); i++) {
if (equal(begin(find_me->state), end(find_me->state), begin((*i)->state)))
return true;
}
return false;
}
void printNode(Node* print){
for(int i = 0; i < 3; i++){
cout << print->state[i] << " ";
}
cout << endl;
}
int locate(Node* find_me){
for(vector<Node*>::iterator i = Head.begin(); i != Head.end(); i++) {
if (equal(begin(find_me->state), end(find_me->state), begin((*i)->state)))
return distance(Head.begin(), i);
}
return -1;
}
void LinkState(Node* head, Node * nxt){
Node* vert = Head[locate(head)];
while(vert->next != NULL){
vert = vert->next;
}
vert->next = nxt;
}
public:
void DFS(){
steps = 0;
//start exploring at initial value
explore(init);
}
void explore(Node* vertex){
//base case to end
if(!isIn(vertex)){
Head.push_back(vertex);
if(vertex->state[1] == 2 || vertex->state[2] == 2){
cout << steps << endl;
printNode(vertex);
return;
}
//generate all possible states and connects them to Head vertex
else{
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
Node conn1 = pour(vertex,i,j);
Node *conn = &conn1;
if(i!=j && !isIn(conn)){
cout << i << " adds water to " << j << endl;
LinkState(vertex, conn);
}
}
}
}
Node* Nextex = vertex;
//printNode(vertex);
while(Nextex != NULL){
//new neighbor
if(!isIn(Nextex)){
//printNode(Nextex);
explore(Nextex);
}
Nextex = Nextex->next;
}
}
//printNode(Nextex);
else{
cout <<"Dead end" << endl;
}
}
//start from init node and show path to solution
void display(){
Node *output;
for(int i = 0; i < Head.size(); i++){
output = Head[i];
while ( output != NULL){
printNode(output);
output = output->next;
}
cout << '#' <<endl;
}
}
};
#endif // _POURINGLIST_
basic driver:
#include "PouringList.h"
int main(){
PouringList s1;
s1.DFS();
}
Edit
I've attempted the suggested fix before (This is what I'm assuming you mean). It still lead to the programming running forever. Also I do not know enough about smartpointers to go and overhaul the application!
Node conn1 = pour(vertex,i,
Node *conn = new Node;
conn = &conn1;
You are storing the address of a local variable in your list.
In explore, you have
Node conn1 = pour(vertex,i,j);
Node *conn = &conn1;
then later pass conn to LinkState, which stores that pointer in your PouringList. All your added nodes will point at the same memory address.
What you should be doing is allocating a new Node and using that (preferably using some sort of smart pointer rather than storing raw pointers so the clean up will happen automatically).