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
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 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++;
}
}
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
My aim is to produce a function that searches for a number already in the list and print that it has been found.
My initial idea was to follow my remove function which searches through the list until it finds a number (to then delete).
This seemed the logical way to code the search function. If this isn't correct how would I modify it to search through my list and display that a number has been found?
I have nodes *head, *current and *temp as well as node pointer next and number as the data type in a class on a .h file.
Thank you.
NOTE - I used my remove() function under the search() function.
#include <iostream>
#include <string>
#include <fstream>
#include "LinkedList.h"
using namespace SDI;
int main()
{
LinkedList menu;
menu.insert(5);
menu.insert(4);
menu.insert(2);
menu.insert(3);
menu.insert(8);
menu.remove(4);
menu.reverse();
menu.display();
menu.search(2);
system("pause");
};
LinkedList::LinkedList()
{
head = NULL;
current = NULL;
temp = NULL;
};
LinkedList::~LinkedList()
{
};
void LinkedList::insert(int add) //insert function, data is stored in add from function body
{
Node* newnode = new Node; //definition of add node, make new node and make node* point to it
newnode->next = NULL; //point and set up to last node in the list (nothing)
newnode->number = add; //adds data to list
if (head != NULL) //if head is pointing to object then we have list
{
current = head; //make current pointer point to head
while (current->next != NULL) //check to see if end at list, is it the last node?
{
current = current->next; //advances current pointer to end of list
}
current->next = newnode; //adds new node next to value already stored
}
else
{
head = newnode; //if we don't have element in list
}
};
void LinkedList::remove(int remove) //remove function, data is stored in remove from function body
{
Node* remove1 = NULL; //searches through for same value in remove and deletes
temp = head;
current = head;
while (current != NULL && current->number != remove) //check if current node is one we want to delete...if not advance current pointer to next one
{
temp = current; //keep temp pointer one step behind
current = current->next; //advance to next node, traverse list till at the end
}
if (current == NULL) //pass through whole list and value not found
{
std::cout << "N/A\n";
delete remove1; //removes spare number floating around in memory
}
else
{
remove1 = current; //pointing to value we want to delete
current = current->next; //advances current pointer to next node
temp->next = current; //stops hole that occurs in list, patches this up
if (remove1 == head) //if pointer is pointing to front of list
{
head = head->next; //advance the head to next
temp = NULL;
}
delete remove1;
}
};
void LinkedList::search(int searchNum)
{
Node* searchnumber = nullptr;
temp = head;
current = head;
while (current != NULL && current->number != searchNum)
{
temp = current;
current = current->next;
}
if (current != NULL)
{
searchnumber = current;
current = current->next;
std::cout << "-" << searchnumber << " Found";
}
else
{
std::cout << "N/A";
}
};
void LinkedList::display()
{
current = head; //point to start of list
while (current != NULL) //while it points to something in list
{
std::cout << current->number; //display list starting from start
current = current->next; //advance to next pointer
}
};
void LinkedList::reverse()
{
Node *new_head = nullptr; //create new head as we want it to start from last element
for (current = head; current;) //same as display, ask it to go through list from head then outside loop assign to new head and switch sides
{
temp = current; //keep temp pointer one step behind
current = current->next; //goes through each element in the list
temp->next = new_head; //scrolls through backwards from new head
new_head = temp;
}
head = new_head; //assign head to new head
};
Your search algorithm seems to be wrong. Change it to :
if (current != NULL) // (current == NULL) is wrong because it means the value wasn't found
{
searchnumber = current;
current = current->next;
std::cout << "-" << searchnumber->number << " Found"; // here searchnumber is the node's address. You need to print its value, so use searchnumber->number
}
And you don't need to remove nodes till you find the desired value.
You can just use your search algorithm to find if a number already in the list. If that's what you want.
While a list is unordered a comparison of search algorithms doesn't have any sense. Simply iterate over all nodes one by one and apply match criteria.
I have looked at other threads here on the topic, but have no been able to use them to solve my problem.
this is the main class definition of a node in the linked list:
class node {
public:
// default constructor
node() {name = ""; prev = NULL; next = NULL;};
// default overloaded
node(string s) {name = s; prev = NULL; next = NULL;};
// item in the list
string name;
// links to prev and next node in the list
node * next, * prev;
};
the above is the node class definition, which is used in another class that generates a linked list. the linkedlist code was given to us, which we had to modify, so I know it works. I have gone through and tested the addition of new nodes in the doubly linked list to be working, and I am now working on removing nodes from this same doubly linked list.
The function to remove a node: http://pastebin.com/HAbNRM5W
^ this is the code I need help with, there is too much to retype
I was told by my instructor that the code that is the problem is the line 56, which reads:
tmp->prev = prev;
I am trying to set the link to the previous node to be the correct one. the case I am trying to work from with the similar if/else loops is whether or not the current node is the last item in the list. if it is the last item (aka curr->next = NULL), then don't set a link using curr->next and stop the loop iteration.
any help / ideas / suggestons / feedback will be greatly appreciated!
void linkedList::remove(string s)
{
bool found = false;
node * curr = getTop(), * prev = NULL;
node * tmp = new node();
while(curr != NULL)
{
// match found, delete
if(curr->name == s)
{
found = true;
// found at top
if(prev == NULL)
{
node * temp = getTop();
setTop(curr->next);
getTop()->prev = NULL;
delete(temp);
} // end if
else
{
// determine if last item in the list
if (curr->next = NULL)
{
// prev node points to next node
prev->next = curr->next;
// delete the current node
delete(curr);
} // end if
// if not last item in list, proceed as normal
else
{
// prev node points to next node
prev->next = curr->next;
// set the next node to its own name
tmp = prev->next;
// set prev-link of next node to the previous node (aka node before deleted)
tmp->prev = prev;
// delete the current node
delete(curr);
} // end else
} // end else
} // end if
// not found, advance pointers
if(!found)
{
prev = curr;
curr = curr->next;
} // end if
// found, exit loop
else curr = NULL;
} // end while
if(found)
cout << "Deleted " << s << endl;
else
cout << s << " Not Found "<< endl;
} // end remove
NULL should be replaced with nullptr
if (curr->next = NULL) { ...
That is an assignment, you want:
if (curr->next == nullptr) { ...
On line 47 I think you say: if prev == nullptr and next is not nullptr , but you use
prev->next = curr->next;
Which doesn't work since prev is nullptr.
For your code, I suggest several things. Isolate the code to find the node with the name you are looking for. The remove method SHOULD only remove a doubly linked node, provided that it is given one.
I know that your remove method takes in a string parameter, but pass that to another function and have that function return the node you are looking for.
It should look something like this:
Node *cur = find("abcd");
Node *prev = cur->prev;
prev->next = cur->next;
Node *n = cur->next;
n->next = cur->prev;
cur->next = NULL; //or nullptr
cur->prev = NULL; //or nullptr
delete cur;
Should look like:
prev->next = curr->next;
prev->next->prev = prev;
delete (curr);
I got lost in all your different conditionals. All you need to do is this:
void linkedList::remove(const std::string& s)
{
node* current = getTop(); // get head node
while (current != nullptr) // find the item you are trying to remove
{
if (current->name == s)
{
break; // when you find it, break out of the loop
}
}
if (current != nullptr) // if found, this will be non-null
{
if (current->prev) // if this is not the head node
{
current->prev->next = current->next;
}
else
{
// update head node
}
if (current->next) // if this is not the tail node
{
current->next->prev = current->prev;
}
else
{
// update tail node
}
// at this point, current is completely disconnected from the list
delete current;
}
}
Here is my code to delete all the nodes having the value passed in the argument.
typedef struct nodetype
{
int data;
struct nodetype * next;
} node;
typedef node * list;
void Linklist::deleteNode(list * head, int value)
{
list current = *head;
list previous = *head;
while(current != NULL)
{
if(current->data != value)
{
previous = current;
current = current->next;
}
else if (current->data == value)
{
previous->next = current->next;
delete current;
current = previous->next;
}
}
}
But here if all the elements in the linklist is say 2, then it should delete all the elements in the linklist and finally head should also become NULL so that if I pass this head to count the number of nodes in the list it should say that the list is empty and other similar operations.
According to my current implementation the head is not becoming NULL for the above mentioned case.
Please suggest the modification so that head should become NULL if the linklist has all the nodes with the same value passed in the function argument.
I modified my code as follows and its working file now
void Linklist::deleteNode(list *head, int value)
{
list * current = head;
list * previous = head;
bool flag = false;
while(*current != NULL)
{
if((*current)->data != value)
{
*previous = *current;
*current = (*current)->next;
}
else if ((*current)->data == value)
{
flag = true;
(*previous)->next = (*current)->next;
delete *current;
*current = (*previous)->next;
}
}
if(!flag)
cout<<"Element not found in the linklist\n";
cout<<"Count is "<<Linklist::count(*head)<<endl;
}