I need to create a linked list of a class member (Binary), and I'm running into an infinite loop problem. The Binary class only contains the degree (int) and a next node pointer.
Within the Binary Class, the implementation for the Binary linked list is being performed inside the set_bit method. The set_bit method takes in two ints, and they are either a 1/0 int (bit) and a degree int. The bit is not needed at this point though.
The set_bit method is below:
void Binary::set_bit(int b, int d){
BinaryNode* current = firstTerm;
BinaryNode* toSet;
if (current == NULL) {
firstTerm = new BinaryNode(d, NULL);
current = firstTerm;
cout << "\nd: " << d << " <--> current degree: " << current->degree << endl;
system("pause");
} else {
while (current != NULL){
firstTerm = new BinaryNode(d, current);
cout << "\nd: " << d << " <--> current degree: " << current->degree << endl;
cout << "first term: " << firstTerm->degree << endl;
system("pause");
}
}
}
on the main.cpp file, I am trying to set the following bits:
b1.set_bit(1, 2);
b1.set_bit(1, 5);
b1.set_bit(1, 0);
b1.set_bit(0, 2);
The method is setting the first bit (2), and gets to the next (5), then begins an infinite loop trying to set the bit.
Where am I going wrong on this?
I've asked my lab instructor for help and he provided me the following code:
Why did the code that the lab instructor not work either?
void Binary ::set_bit( int b , int d ){
BinaryNode * current = firstTerm;
if (current == NULL ){
firstTerm = new BinaryNode(d,NULL); // Corrected Line
}
while (current != NULL ){
firstTerm = new BinaryNode(d,firstTerm); // Corrected Line
}
}
Thanks
Of course you would end up with infinite loop, because when u try inserting the second node, current != NULL is always true, which means the else section is called. Unfortunately, the there is a while loop inside whose condition is always true.
Related
/********************************************
* Remove the last employee from the list *
********************************************/
void EmployeeList::Remove()
{
newEmployee * nextToEnd = head,
* last = head->Next();
//THIS IS THE PROBLEM
//no nodes
if(head == NULL)
return;
//remove the only employee in the list
if(head->Next()== NULL)
{
cout << "\n\t\tEmployee ID " << head->empID() << " and salary $"
<< head->ySalary() << " have been removed.\n";
head = NULL;
delete head;
}
else
{
// remove the last employee of the list
while(last->Next() != NULL)
{
nextToEnd = last;
last = last->Next();
}
cout << "\n\t\tEmployee ID " << last->empID() << " and salary $"
<< last->ySalary() << " have been removed.\n";
delete last;
nextToEnd->SetNext(NULL);
}
}
having problem when trying to remove from an empty list. I know i cant remove if it is empty but i would instead of crashing the program to display "The Employee List is empty.
I specified where I think the problem hoping someone can help me out to figure it out.
All you have to do is what's already shown in the code. Notice how it outputs text to console using cout. Change the if statement where you specified the 'problem' is to output a message and then return.
But your program crashing has nothing to do with what you have marked. It is crashing because of head->Next(). You can't call a method on an object that is NULL. That should be occurring after the if (head == NULL) check.
Here is some code that I have made that should copy all the nodes in a linked data type correctly, but it is not working. I have checked my logic and wrote it on paper many times, yet it still isn't working. Am I doing something wrong on this part of the code? Is my use of pointers to copy nodes accurate? The part of my Constructor test that goes haywire is the part that starts to print out what's in the queue.
void LinkedQueue<ItemType>::CopyNodesFrom(const LinkedQueue& a_queue)
{
Node<ItemType>* orig_chain_ptr = a_queue.front_ptr_; // Points to nodes in original chain
if (orig_chain_ptr == nullptr) {
front_ptr_ = nullptr; // Original queue is empty
back_ptr_ = nullptr;
return;
}
// Copy first node
front_ptr_ = new Node<ItemType>();
front_ptr_->SetItem(orig_chain_ptr->GetItem());
// Advance original-chain pointer
orig_chain_ptr = orig_chain_ptr->GetNext();
// Copy remaining nodes
Node<ItemType>* new_chain_ptr = front_ptr_; // Points to last node in new chain
Node<ItemType>* temp_ptr;
while (orig_chain_ptr != nullptr) {
temp_ptr = new Node<ItemType>(orig_chain_ptr->GetItem() );
new_chain_ptr->SetNext(temp_ptr);
orig_chain_ptr = orig_chain_ptr->GetNext(); //Advance Our original pointer
new_chain_ptr = new_chain_ptr->GetNext(); //Advance our new chain pointer
} // end while
new_chain_ptr->SetNext(nullptr);
back_ptr_ = new_chain_ptr;
} // end copy constructor
#include <iostream>
#include <string>
#include "LinkedQueue.h" // ADT Queue operations
using namespace std;
void CopyConstructorAndAssignmentTester() {
LinkedQueue<string> queue;
string items[] = {"zero", "one", "two", "three", "four", "five"};
for (int i = 0; i < 6; i++) {
cout << "Adding " << items[i] << endl;
bool success = queue.Enqueue(items[i]);
if (!success)
cout << "Failed to add " << items[i] << " to the queue." << endl;
}
cout << "Queue contains, from front to back, zero one two three four five." << endl;
cout << "Checking Copy Constructor tester " << endl;
LinkedQueue<string> copy_of_queue(queue);
cout << "Copy of queue contains, from front to back, ";
for (int i = 0; i < 6; i++)
{
cout << " " << copy_of_queue.PeekFront();
copy_of_queue.Dequeue();
}
cout << "." << endl;
/*
cout << "Checking Assignment Operator tester " << endl;
LinkedQueue<string> assigned_queue;
assigned_queue.Enqueue("ha");
assigned_queue.Enqueue("ba");
assigned_queue = queue;
cout << assigned_queue << endl;*/
/* cout << "Assigned queue contains, from front to back, ";
for (int i = 0; i < 6; i++)
{
cout << " " << assigned_queue.PeekFront();
assigned_queue.Dequeue();
}
cout << "." << endl;
cout << "Original queue contains, from front to back,";
for (int i = 0; i < 6; i++) {
cout << " " << queue.PeekFront();
queue.Dequeue();
}
cout << "." << endl << endl; */
} // end copyConstructorTester
int main()
{
CopyConstructorAndAssignmentTester();
char a;
cin >> a;
//ConcatenateTester();
//return 0;
} // end main
EDIT: Oh crap, this stumps more people than I thought. XD. I thought I made a blatantly obvious mistake.
This may not be the answer you are looking for, and I'm finding it difficult to spot mistakes in your code lacking the full information of the states being manipulated.
The linked list logic looks all right: nothing jumps out at me as being faulty there in terms of the logic used to copy. Put in a distilled form:
first_node = last_node = new Node(other.first_node->data);
for (Node* other_node = other.first_node->next; other_node; other_node = other_node->next)
{
Node* new_node = new Node(other_node->data);
last_node->next = new_node;
last_node = new_node;
}
last_node->next = nullptr;
I believe this is what you have and it should be correct in terms of the overall logic. Any problems will probably be found elsewhere. Nevertheless, it should make your life easier to reduce the number of states you're working with. This 'new_chain_ptr' is unnecessary and you can just write out the results to 'back_ptr_' directly.
However, I have a different suggestion. You have the rest of the Queue working correctly, yes, including these methods like 'Enqueue'? If so, your copy constructor can be more trivially implemented just using what works already. Start with the state for an empty queue, and then read the elements from the other queue and 'Enqueue' those elements into your copy. Now you can avoid getting yourself tangled up in the low-level linked list logic by utilizing the parts you already know are functioning like so:
// Create empty queue.
first_node = last_node = nullptr;
// Enqueue elements from other queue.
for (Node* other_node = other.first_node; other_node; other_node = other_node->next)
Enqueue(other_node->data);
It might cost you an additional branch or so per iteration but remember that correctness always precedes efficiency, and you can come back and optimize once you have it working. Remember to handle self-assignment if the logic cannot work properly in those cases.
And yes, a debugger will give you a massive edge in accelerating the understanding of the nature of your code in addition to spotting mistakes more quickly.
I'm writing a code to index the skills available to a user in a game, constructed as a linked list. I've throughly tested the function that populates the list and it seems to be working correctly (so the head pointer for the list shouldn't be null). When I attempt to traverse the list to set values in the skill, before any of the code which writes to memory within the list gets to execute the program is crashing when I initialise the temp pointer within the search function of the list to the head pointer.
What makes this additionally weird to me is that it worked fine (and I had tested this fairly thuroughly) until I added in a list to store a list of available items, and may just be missing an odd interaction between the two when I populate them.
The specific error is that the pointer is supposedly accessing memory index 0x000000c to write to, but I don't see how the code at that point is dealing with a null pointer at all (since after 10 runs of the program the OS shouldn't be allocating that block of memory to the temp pointer every time and nothing else should be null.
I'm probably just ramblind at this point so here's the code:
The function that causes the error according to the debugger:
void Mechanics::setSkillValue(int index, int value)
{
Skill *temp = FirstSkill; // << The error is happening on this line //
while((temp != NULL)&&(temp->index != index))
{
temp = temp->next;
}
if (temp == NULL)
{
cout << "%";
}
else temp->setValue(value);
// cout << temp->returnValue(); //This was a test check, not needed for anything
}
The Function that's supposed to populate the skill and item lists.
void Mechanics::Populate()
{
ifstream skillstream("Skills.txt");
if(skillstream.is_open())
{
while(skillstream.good())
{
Skill *newskill;
int indexval;
string skillindex;
string skillname;
string skilldescription;
cout << "TP4" << endl; //TEST POINT
getline(skillstream, skillindex);
cout << skillindex;
getline(skillstream, skillname);
cout << skillname;
getline(skillstream, skilldescription);
cout << skilldescription; cout << endl;
indexval = atoi(skillindex.c_str());
newskill = new Skill(skillname, skilldescription,indexval);
//cout << "TP5" << endl; //TEST POINT
if(newskill == NULL) cout << "NULL!!!";
addSkill(newskill);
}
}
ifstream itemstream("Items.txt");
if(itemstream.is_open())
{
while(itemstream.good())
{
Item *newitem;
int indexval;
string skillindex;
string skillname;
string skilldescription;
string abilitydescription;
string valueSTR;
string typeSTR;
int value;
int type;
int numeric[5];
// cout << "TP4" << endl; //TEST POINT
getline(itemstream, skillindex);
// cout << skillindex;
getline(itemstream, skillname);
// cout << skillname;
getline(itemstream, skilldescription);
// cout << skilldescription;
getline(itemstream, abilitydescription);
getline(itemstream, valueSTR);
value = atoi(valueSTR.c_str());
getline(itemstream,typeSTR);
type = atoi(typeSTR.c_str());
for (int i=0; i < 5; i++)
{
string numericSTR;
getline(itemstream,numericSTR);
numeric[i]=atoi(numericSTR.c_str());
}
indexval = atoi(skillindex.c_str());
newitem = new Item(indexval, skilldescription, skillname, abilitydescription, value, type, numeric);
//cout << "TP5" << endl; //TEST POINT
// if(newskill == NULL) cout << "NULL!!!";
addItem(newitem);
}
}
The function that's supposed to actually add a skill to the skill list:
void Mechanics::addSkill(Skill *nskill)
{
Skill *temp = FirstSkill;
if(FirstSkill == NULL)
{
FirstSkill = nskill;
//cout << "TP1" << endl; //TEST POINT
//FirstSkill->printname();
}
else
{
while((temp->next != NULL))
{
temp = temp-> next;
//cout << "TP2" << endl; //TEST POINT
//temp->printname(); cout << endl;
}
if (FirstSkill != NULL)
{
temp->next = nskill;
nskill->next = NULL;
}
}
}
The code that I have is somewhat extensive so I'm only going to include the blocks which are potentially interacting with the function that's throwing up the error.
Thanks in advance for reading through this, and any assistance you're able to offfer, I've been banging my head against this for about 6 hours now and I've lost the perspective to actually track this one down.
so I have been trying to get an old c++ binary search tree program of mine to work.It compiles and runs but I do not get the results I would expect. If I insert c,d,a,b in that order and try to remove c, my remove function skips the if conditionals that find in order successors. Why are those 2 else if conditionals skipped?
Also it is compiled using gcc.
Node::Node(string nodeItem,
int nodeLine){
item=nodeItem;
vector<int> tempVector;
tempVector.push_back(nodeLine);
lines=tempVector;
leftPtr = NULL;
rightPtr = NULL;
}
// recursive method for finding node containing the word
Node* BST::find(string data, Node *curr) {
if(curr==NULL) {
cout << data << " is not in the tree" << endl;
return curr;
}
if(curr->getItem().compare("theplaceholder")==0){
return curr;
}
string tempItem = curr->getItem();
//this if statement is if I am inserting a word that is already in the tree
// or if I am removing the word from the tree
if(data.compare(tempItem)==0){
return curr;
}
else if(data.compare(tempItem)<0){
return find(data,curr->getLeftPtr());
}
else{
return find(data, curr->getRightPtr());
}
}
void BST::insert(string data, int fromLine) {
Node *curr;
curr=find(data, root);
if(curr!=NULL && curr->getItem().compare("theplaceholder")==0){
curr->setData(data);
curr->addLines(fromLine);
}
if(curr==NULL){
// I want to point to a nonNull node.
// I am making a new node and having curr point to that instead of NULL
//then I set it to
curr=new Node(data, fromLine);
cout <<curr->getItem() << endl;
vector<int> foundLines=curr->getNodeLines();
//cout<< "The word " <<curr->getItem() << " can be found in lines ";
if(foundLines.empty())
cout << "foundLines is empty";
int size=foundLines.size();
for(int count=0; count<size; count++){
//cout << foundLines[count] << ", ";
}
}
if(curr->getItem()==data){
curr->addLines(fromLine);
}
}
// remove method I am trying to check for in order successors to swap with the deleted node.
void BST::remove(string data) {
Node *curr=root;
Node *temp=find(data, curr);
if(temp==NULL){
cout << " nothing to remove" << endl;
}
else if(temp->getRightPtr()!=NULL){
curr=temp->getRightPtr();
cout << curr->getItem() << endl;
while(curr->getLeftPtr()!=NULL){
curr=curr->getLeftPtr();
cout << curr->getItem() << endl;
}
temp->setData(curr->getItem());
temp->setLines(curr->getNodeLines());
delete curr;
curr=NULL;
}
else if(temp->getLeftPtr()!=NULL){
cout <<"if !temp->getLeftPtr" << endl;
curr=temp->getLeftPtr();
cout << curr->getItem() << endl;
while(curr->getRightPtr()!=NULL){
curr=curr->getRightPtr();
cout << curr->getItem() << endl;
}
temp->setData(curr->getItem());
temp->setLines(curr->getNodeLines());
delete curr;
curr=NULL;
}
else{
cout <<"else delete temp" << endl;
delete temp;
temp=NULL;
}
}
The reason this line
else if(temp->getRightPtr()!=NULL){
never succeeds is that you never set the right pointer on any node - getRightPtr can only return null. If you'd examined the state of your tree in the debugger after you'd built it or if you stepped through the insert function you'd probably have seen this. The problems are:
your find function doesn't return null if the node isn't in the tree, whereas your insert function expects it will
your insert function needs to locate the position in the tree where this node should be - either through fixing the find function or on its own, then create a new node AND add a reference to it from the parent node, on either the left or right side as appropriate
your insert function appears the line number to the first-inserted node twice: once when you overwrite the placeholder and once at the end of insert (rather than use a placeholder here I'd probably have initialised root to be null and instead set root = curr when you create the first node)
your remove function needs to do more work when promoting the highest node from the left-hand branch; it needs to
correctly clean up that node from it's previous parent - at the moment you delete the object but leave any dangling pointers alone
promote any children of that node before you move it to take its previous slot
i.e.
D C
/ \ / \
A E remove 'D' A E
\ => 'C' is highest on left \
C but need to move B to C B
/
B
I am implementing a tree which is a Binary Expression Tree. The leaf nodes are numbers, non-leaf nodes are math operators. Succesfully implemented printInorder,PostOrder, PreOrder, evaluate. But stucked with the printLevel().
Here is my int main ()
int main()
{
EXTree myTree;
string tests[] = {"2.1*3.1+4.2", "(2.0+1.3)/1.4", "2.*(1.3+1.4)","1.2*(1.3+1.4/0.5)","1.2*(1.3+1.4/0.5)-4.4", "1.2*(1.3+1.4/0.5)- (9/3)"};
for (int i=0; i < 6; i++)
{
myTree.build (tests[i]);
myTree.printInorder();
myTree.printPreorder();
myTree.printPostorder();
myTree.printLevel(); //Starting from level = 0
cout << "Evaulating myTree = " << format(myTree.evaluate(),2) << endl;
myTree.removeAll(); // removes all the nodes
}
}
printLevel(); only prints the level of the tree given above and its initally 0.
and here is my printLevel function.
void EXTree:: printLevel()
{
queue<Node*> levelq;
levelq.push(root);
cout << "Current Level is: ";
while( levelq.size() > 0 )
{
Node *cur = levelq.front();
cout << cur->Root << " ";
levelq.pop();
if (cur->Left) levelq.push(cur->Left);
if (cur->Right) levelq.push(cur->Right);
}
cout << endl;
}
But I really didnt understand how to implement the printLevel. Appreciate for any help to clarify it.
I just implemented the inOrder algorith to my printLevel and tried to change it but still didnt get it.
Since you have no problem with recursion, this would work without queue:
void EXTree:: printLevel()
{
int currentLevel = 0;
if (root)
{
cout << "Current Level is: ";
printLevelHelper(root,currentLevel);
}
else
cout << "This BST is Empty\n";
}
// Declare a private method:
void EXTree:: printLevelHelper(Node* &n, int ¤tLevel)
{
cout << currentLevel << ' ';
if (n->Left)
{
currentLevel++;
printLevelHelper(n->Left,currentLevel);
currentLevel--;
}
if (n->Right)
{
currentLevel++;
printLevelHelper(n->Right,currentLevel);
currentLevel--;
}
}
When using Breadth First Search to print the nodes on one level immediately adjacent to each other, you'd just observe when the leftmost child of the leftmost node on the current level pops out of the queue: this must be the start of the next level. I could easily write the code but I'd guess it would incomprehensible for you and this homework is for you (I think you want to label your post appropriately as homework, BTW). Most of your implementation looks like a straight forward implementation. The only thing missing is detecting that the next level is reached.