I'm trying to write an insert method for my binary search tree class. I want it to be able to insert a new value into a tree that already has an existing node with this same data value must cause a new node to be created in the right subtree of the existing node. Here's my code. I'm getting an unhandled exception error while trying to compile. I don't know what I did wrong there. If someone can explain the reason why the compiler is giving me error, it would be great. Thanks :)
template <class elemType>
void bSearchTreeType<elemType>::insert
(const elemType& insertItem)
{
nodeType<elemType> *current; //pointer to traverse the tree
nodeType<elemType> *trailCurrent; //pointer behind current
nodeType<elemType> *newNode; //pointer to create the node
newNode = new nodeType<elemType>;
newNode->info = insertItem;
newNode->lLink = NULL;
newNode->rLink = NULL;
if (root == NULL)
root = newNode;
else
{
current = root;
while (current != NULL)
{
trailCurrent = current;
if (current->info == insertItem)
{
current = current->rLink;
trailCurrent->rLink = newNode;
if (newNode->info <= current->info) //this is where the compiler say the error is
newNode->rLink = current;
else
newNode->lLink = current;
}
else if (current->info > insertItem)
current = current->lLink;
else
current = current->rLink;
}//end while
if (trailCurrent->info < insertItem)
trailCurrent->rLink = newNode;
else if (trailCurrent->info > insertItem)
trailCurrent->lLink = newNode;
}
}//end insert
You should make a deal with yourself. This deal can be like this:
The left subtree will have values less or equal than the one in the root and so on.
In code you have:
if (trailCurrent->info < insertItem)
trailCurrent->rLink = newNode;
which after the deal would be like this:
if (trailCurrent->info <= insertItem)
trailCurrent->rLink = newNode;
I'm fairly certain this is what you're trying to do:
template <class elemType>
void bSearchTreeType<elemType>::insert(const elemType& insertItem)
{
nodeType<elemType> **pp = &root;
while (*pp)
{
if (insertItem < (*pp)->info)
pp = &(*pp)->lLink;
else if ((*pp)->info < insertItem)
pp = &(*pp)->rLink);
else break;
}
// note: this is cleaner if the the nodeType constructor
// is parameterized. (hint hint)
nodeType<elemType> *p = new nodType<elemType>;
p->info = insertItem;
p->lLink = NULL;
if (*pp)
{
p->rLink = (*pp)->rLink;
(*pp)->rLink = p;
}
else
*pp = p;
}
How it works
The basics of finding an insertion point for a new non-existing key are mundane, so I'll not cover them. The case of locating an existing key is, however, interesting. We use a pointer-to-pointer to hold the address of each node pointer we encounter while walking down the tree. When we have a match the loop will exit and *pp will not be null. When that happens, our new node has it's right-pointer set to the matched right-pointer, and the matched node's right-pointer becomes the new node. The remainder of the tree remains as-is.
I.e. adding a second 7 in this:
5
3 7
2 4 6 8
results in
5
3 7
2 4 6 7
8
then adding another 3 results in:
5
3 7
2 3 6 7
4 8
All of this, of course, assuming i understood the problem.No attempt at rotations or balancing is done. That I leave to you.
Not sure if this is correct but
trialCurrent = current;
trialCurrent is equal to current
if(current->info == insertItem)
current = current->rLink;
trialCurrent->rlink = newnode;
current is equal to current->rLink, then wouldn't trialCurrent->rLink be equal to current?
Related
I'm new to pointers and I'm a bit confused.
I have written a function which merges and sorts two sorted linked lists. However, when I print the list after calling the function it does not have all the values of the new merged list. While debugging the code and examining the variables and memory locations, it looks like it skips over the locations and just jumps to the last memory location. After the function executes I need to have the values in a new list and leaving list1 and list2 empty. This is my method in the header file:
template <class Type>
void orderedLinkedList<Type>::mergeLists(orderedLinkedList<Type> &list1, orderedLinkedList<Type> &list2)
{
nodeType<Type> *lastSmall; //pointer to the last node of the merged list.
nodeType<Type> *first1 = list1.first;
nodeType<Type> *first2 = list2.first;
if (list1.first == NULL){ //first sublist is empty
this->first = list2.first;
list2.first = NULL;
}
else if (list2.first == NULL){ // second sublist is empty
this->first = list1.first;
list1.first = NULL;
}
else{
if (first1->info < first2->info){ //Compare first nodes
this->first = first1;
first1 = first1->link;
lastSmall = this->first;
}
else{
this->first = first2;
first2 = first2->link;
lastSmall = this->first;
}
while (first1 != NULL && first2 != NULL)
{
if(first1->info < first2->info){
lastSmall->link = first1;
lastSmall = lastSmall->link;
first1 = first1->link;
}
else{
lastSmall->link = first2;
lastSmall = lastSmall->link;
first2 = first2->link;
}
} //end while
if (first1 == NULL) //first sublist exhausted first
lastSmall->link = first2;
else //second sublist exhausted first
lastSmall->link = first1;
list1.first = NULL;
list1.last = NULL;
list2.first = NULL;
list2.last = NULL;
}
}
Then in my main.cpp I have:
int main()
{
orderedLinkedList<int> list1;
orderedLinkedList<int> list2;
orderedLinkedList<int> newList;
list1.insert(2);
list1.insert(6);
list1.insert(7);
list2.insert(3);
list2.insert(5);
list2.insert(8);
newList.mergeLists(list1, list2);
newList.print();
return 0;
}
My print function just in case:
template <class Type>
void linkedListType<Type>::print() const
{
nodeType<Type> *current; //pointer to traverse the list
current = first; //set current so that it points to
//the first node
while (current != NULL) //while more data to print
{
cout << current->info << " ";
current = current->link;
}
}//end print
Could someone please tell me what I am doing wrong here? The output should be 2 3 5 6 7 8 but instead it's 2 3 7 8.
Thanks
EDIT:
Here is my insertion function. Note that this function is from the book I'm working with. It is included in the same class that I need to add the mergeLists method to. It is written specifically for ordered lists:
template<class Type>
void orderedLinkedList<Type>::insert(const Type& newItem)
{
nodeType<Type> *current;
nodeType<Type> *trailCurrent;
nodeType<Type> *newNode;
bool found;
newNode = new nodeType<Type>;
newNode->info = newItem;
newNode->link = NULL;
//case1 list is empty
if(this->first == NULL)
{
this->first = newNode;
this->last = newNode;
this->count++;
}
else //if the list is not empty
{
current = this->first;
found = false;
while(current != NULL && !found)
{
if(current->info >= newItem)
found = true;
else
{
trailCurrent = current;
current = current->link;
}
//case2 insert newNode at the head
if(current == this->first)
{
newNode->link = this->first;
this->first = newNode;
this->count++;
}
else //case 3
{
trailCurrent->link = newNode;
newNode->link = current;
if(current == NULL)
this->last = newNode;
this->count++;
}
}
}
}
The 3 cases as according to the book are:
Case 1:
The list is initially empty. The node containing the new item is the only node
and, thus, the first node in the list.
Case 2:
The new item is smaller than the smallest item in the list. The new item goes at
the beginning of the list. In this case, we need to adjust the list’s head pointer—
that is, first. Also, count is incremented by 1.
Case 3:
The item is to be inserted somewhere in the list.
Case 3a:
The new item is larger than all the items in the list. In this case, the new
item is inserted at the end of the list. Thus, the value of current is NULL
and the new item is inserted after trailCurrent. Also, count is incremented
by 1.
Case 3b:
The new item is to be inserted somewhere in the middle of the list. In this
case, the new item is inserted between trailCurrent and current.
Also, count is incremented by 1.
The bug is in your insertion method. When you call print on the lists after inserting, you will note that the last value gets overriden:
list1.insert(2); list1.print();
list1.insert(6); list1.print();
list1.insert(7); list1.print();
list2.insert(3); list2.print();
list2.insert(5); list2.print();
list2.insert(8); list2.print();
will output:
2
2 6
2 7
3
3 5
3 8
This is because every iteration trailCurrent->link = newNode; gets called, cutting of the list the first time this happens.
So for example when 7 is inserted in list1, the loop will first set trailCurrent->link to 7 when trailCurrent is 2, and then continue and set trailCurrent->link to 7 when trailCurrent is 6. But since 2 now points to 7 and not to 6, the chain is lost, and you're stuck with only 2 and 7.
Get another book
The book you are using to learn this is outdated. C style pointers and manual memory allocation should not be used in modern C++. Try to get a modern book that teaches how to use smart pointers and modern collections, and that teaches proper debugging techniques, so you can easily detect problems as the one you stumbled over now.
Thanks to everyone who has tried to help. In the end it was a simple logic error.
I inadvertently added a curly bracket to the end of my while loop in my insertion method which resulted in the loop executing code that it wasn't supposed to more than once causing strange behavior. See the corrected code below:
while(current != NULL && !found)
{ //<-- Removed this
//code
this->count++;
}
} //<-- Removed this
And now the working code is:
template<class Type>
void orderedLinkedList<Type>::insert(const Type& newItem)
{
nodeType<Type> *current;
nodeType<Type> *trailCurrent;
nodeType<Type> *newNode;
bool found;
newNode = new nodeType<Type>;
newNode->info = newItem;
newNode->link = NULL;
//case1 list is empty
if(this->first == NULL)
{
this->first = newNode;
this->last = newNode;
this->count++;
}
else //if the list is not empty
{
current = this->first;
found = false;
while(current != NULL && !found)
if(current->info >= newItem)
found = true;
else
{
trailCurrent = current;
current = current->link;
}
//case2 insert newNode at the head
if(current == this->first)
{
newNode->link = this->first;
this->first = newNode;
this->count++;
}
else //case 3 insert newNode anywher in the list
{
trailCurrent->link = newNode;
newNode->link = current;
if(current == NULL)
this->last = newNode;
this->count++;
}
}
}
I am currently learning about circular linked lists and I am having problems with a circular linked list template. It is derived from an ADT linked list type.
The problems I am having are with deletion of nodes, in some occasions the program will just crash when I delete them. I know I need to implement a dummy node of some sort when I create a list to prevent this happening however I do not know were in the code to do this.
I have looked at other posts regarding this however I am still lost.
If anyone could share some guidance into how to implement this I would be so
grateful.
Thank you
Insert:
template <class Type>
void unorderedCircularLinkedList<Type>::insertFirst(const Type& newItem)
{
nodeType<Type> *newNode;
nodeType<Type> header; <--- implement here?
header.link = &header; <---- dereference the header?
newNode = new nodeType<Type>; //create the new node
newNode->info = newItem; //store the new item in the node
if (first == NULL)
{
first = newNode;
last = first;
last->link = first;
}
else
{
last->link = newNode; //make last point to new node
newNode->link = first; //make new node point to first
first = newNode; //make first point to new node
}
count++; //increment count
}
Delete:
template <class Type>
void unorderedCircularLinkedList<Type>::deleteNode(const Type& deleteItem)
{
nodeType<Type> *current; //pointer to traverse the list
nodeType<Type> *trailCurrent; //pointer just before current
bool found;
if (first == NULL) //Case 1; the list is empty.
cout << "Cannot delete from an empty list."
<< endl;
else
{
if (first->info == deleteItem) //Case 2
{
current = first;
count--;
if (first->link == first) //the list has only one node
{
first = NULL;
last = NULL;
}
else if (first->link == last) //the list has two nodes
{
first = first->link;
first->link = first;
last = first;
}
else
{
first = first->link;
last->link = first;
}
delete current;
}
else //search the list for the node with the given info
{
found = false;
trailCurrent = first; //set trailCurrent to point to the first node
current = first->link; //set current to point to the second node
/* set pointer to point to the last node*/
while (current != NULL && !found)
if (current->info != deleteItem)
{
trailCurrent = current;
current = current->link;
}
else
found = true;
if (found) //Case 3; if found, delete the node
{
trailCurrent->link = current->link;
if (current == last)
first = first->link;
delete current;
count--;
//delete the node from the list
}
else
cout << "The item to be deleted is not in the list." << endl;
}
}
}
your curly braces are messed up
if (first->info == deleteItem) //Case 2
{
current = first;
count--;
//missing '}' here
if (first->link == first) //the list has only one node
{
first = NULL;
last = NULL;
}
and i think there's an extra one at the end you will find out when you add the above one
I have a base class called linkList and two derived class. One order link list class and unorder link list class. My order link list class is not working and i have no idea why.When i insert 3 numbers into the list it work but when i insert more than 4 values it messes up. It will also say the length of the list is larger than what it actually is. [enter image description here][1]
void insert(const T& newItem){
nodeType<T> *current;
nodeType<T> *trailCurrent=nullptr;
nodeType<T> *newNode;
bool found;
newNode = new nodeType<T>;
newNode->info = newItem;
newNode->next = nullptr;
//if the list is empty add to empty list
if (this->first == nullptr){
this->first = newNode;
this->last = newNode;
this->count++;
}
else {
current = this->first;
found = false;
while (current != nullptr && !found){
if (current->info >= newItem)
found = true;
else{
trailCurrent = current;
current = current->next;
}
//if current value is first item into the list insert into the front
if (current == this->first){
newNode->next = this->first;
this->first=newNode;
this->count++;
}
else{
trailCurrent->next = newNode;
newNode->next=current;
if (current == nullptr)
this->last = newNode;
this->count++;
}
}
}
}
I will preface to say that this is my first question. I am currently getting my Masters degree in Information Security and I had to take C++ programming this semester. So this is homework related. I am not looking for you to answer my homework but I am running into a peculiar situation. I have created the program to work with a doubly linked list and everything works fine. However when I have the user create a list of values the first node keeps returning 0. I have tried finding some reading on this and I cannot locate any reference to it. My question is then is the header node(first node) always going to be zero? Or am I doing something wrong.
case: 'C':
cout<<"Please enter a list:"<<endl;
while(n!=-999){
myList.insert(n);
cin>> n;}
break;
I now enter: 12321, 1234,64564,346346. The results in 0, 12321, 1234, 64564,346346. Is this what should happen or am I doing something wrong? Also as this is my first post please feel free to criticize or teach me how to color code the keywords.
Anyway this is a homework assignment so I am only looking for guidance and constructive criticism.
Thank you all in advance
So I cannot figure out the comment sections on this forum so I will edit the original post
The first section is the constructor code:
template <class Type>
doublyLinkedList<Type>::doublyLinkedList()
{
first= NULL;
last = NULL;
count = 0;
}
Then there is my insert function :
template <class Type>
void doublyLinkedList<Type>::insert(const Type& insertItem)
{
nodeType<Type> *current; //pointer to traverse the list
nodeType<Type> *trailCurrent; //pointer just before current
nodeType<Type> *newNode; //pointer to create a node
bool found;
newNode = new nodeType<Type>; //create the node
newNode->info = insertItem; //store the new item in the node
newNode->next = NULL;
newNode->back = NULL;
if(first == NULL) //if the list is empty, newNode is
//the only node
{
first = newNode;
last = newNode;
count++;
}
else
{
found = false;
current = first;
while (current != NULL && !found) //search the list
if (current->info >= insertItem)
found = true;
else
{
trailCurrent = current;
current = current->next;
}
if (current == first) //insert newNode before first
{
first->back = newNode;
newNode->next = first;
first = newNode;
count++;
}
else
{
//insert newNode between trailCurrent and current
if (current != NULL)
{
trailCurrent->next = newNode;
newNode->back = trailCurrent;
newNode->next = current;
current->back = newNode;
}
else
{
trailCurrent->next = newNode;
newNode->back = trailCurrent;
last = newNode;
}
count++;
}//end else
}//end else
}//end
Then I have an initialization function too:
template <class Type>
void doublyLinkedList<Type>::initializeList()
{
destroy();
}
Did I miss anything?
You insert first, then read the input.
Just by the content of your code, I believe maniek has the right answer, so kindly upvote him if/when you find the same, and not this answer please. This is for Craig to understand how to reorder his loop so it reads, tests, breaks if needed, else inserts.
while (cin >> n && n != 999)
myList.insert(n);
There are about a dozen ways to code this, with a for-loop, do-while loop, etc, but that should get you running. Again, please consider up-voting maniek's answer if it solves your problem, and please mark the green check on it (and any other answers on StackOverflow that provide answers you're looking for).
I am writing an Add function to add nodes to a binary tree non recursively.
I have run into the problem of only being able to produce one level deep binary tree. I debugged it and I know where the problem is but can't figure out how to fix it. Maybe fresh pair of eyes will see something i dont...
The problem is that my temp node is being reset to the root value every new function call and hence, adding nodes linearly.
Anyways, here is the function:
void BinaryTreeNonRec::add(int num){
treeNode *temp, *parent;
if (root==NULL) {
root = new treeNode;
root->data=num;
root->left=0;
root->right=0;
temp=root;
printf("value is root \n");
} else {
temp=root;
while (temp!=NULL) {
if (num <= temp->data){
parent = temp;
temp=temp->left;
//root =temp;
printf("value is to the left \n");
} else {
parent =temp;
temp=temp->right;
//root=temp;
printf("value is to the right \n");
}
}
parent = new treeNode;
parent->data=num;
parent->left=NULL;
parent->right=NULL;
temp=parent;
}
}
Thanks for any kind of help.
You are not adding the new node to the tree, just running down the tree and filling parent with a new node, but never adding it to the tree, change below code:
parent = new treeNode;
parent->data=num;
parent->left=NULL;
parent->right=NULL;
temp=parent;
To:
treeNode *newNode = new treeNode;
newNode->data = num;
newNode->left = NULL;
newNode->right = NULL;
//Now insert the new node BELOW parent
if(num <= parent->data)
parent->left = newNode;
else
parent->right = newNode;
The problem might be that you never add your new node to the tree.
parent = new treeNode;
parent->data=num;
parent->left=NULL;
parent->right=NULL;
temp=parent;
You assign your new node to temp and parent, which are temporary variables and therefore don't exist outside of the function. What you have to do is assign your new node to either parent->left or parent->right, depending on which side your new input lies, in order to link it into the the tree. Therefore what you want to do is something like the following:
temp = new treeNode;
temp->data=num;
temp->left=NULL;
temp->right=NULL;
if(num < parent->data)
parent->left = temp;
else
parent->right = temp;
Algo
if root == null Create new node assign to Root
Keep iterating based on comparison with rootNode until reach any leaf Node
check if num <= parent(leaf) Insert into left ELSE insert into right
Code
private void insertItrInBST(int num){
Node temp = root,parent = root;
if(root == null){
root = getNewNode(num);
}else{
temp = root;
while(temp != null){
if(num <= root.data){
parent = temp;
temp = temp.left;
}else{
parent = temp;
temp = temp.right;
}
}
Node newNode = getNewNode(num);
if(num <= parent.data){
parent.left = newNode;
}else{
parent.right = newNode;
}
}
}