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.
Related
In place of *head_ref = temp->next;, why can't I assign it as *head_ref = *head_ref->next?
Why should I use temp? Aren't they pointing to the same place?
class Node{
public:
int data;
Node* next;
};
void deleteNode(Node** head_ref, int key){
Node* temp = *head_ref;
Node* prev = NULL;
if(temp!=NULL && temp->data==key){
*head_ref = temp->next;
delete temp;
return;
}
else{
while(temp!=NULL && *head_ref->data!=key){
prev = temp;
temp = temp->next;
}
}
Your code does not compile, *head_ref->data should be (*head_ref)->data.
The reason why you should use temp is that you want to modify *head_ref only if the element you want to delete is the head element. If you delete any other element of the list, the head pointer must stay the same.
But your code is wrong anyway. You're doing things in the wrong order. You must first find the element you want to delete, and then handle the deletion.
Your code handles the deletion first and then finds the element to delete which is absurd.
You want this:
void deleteNode(Node** head_ref, int key) {
Node* current = *head_ref;
Node* previous = NULL;
// find element to delete
while (current && current->data != key)
{
previous = current;
current = current->next;
}
// if current is NULL here then the element has not been found
if (current != NULL)
{
// element found,
// current points to element found
// previous points to previous element or NULL if current is head
if (previous == NULL)
{
// deleting head element -> we need to update head_ref
*head_ref = current->next;
}
else
{
// deleting any other element -> update next pointer of previous element
previous->next = current->next;
}
delete current;
}
}
That being said, this is rather C code than C++ code. You should use standard containers rather than making your own, or at least use C++ idioms such as constructors.
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 am trying to write a reverse print function as part of a doubly linked list. Here are the relevant functions that I have written:
void PLAYER::AddNode(int addID, std::string addName){
nodePtr n = new node; //creates a new node pointer
n->next = NULL; //Make next null
n->prev = NULL; // this will set this to be the ending node
n->ID = addID; //These two lines pass the information into the node
n->name = addName; // ID# and Name Information
if(head != NULL){ // This checks to see if a list is set up.
curr = head; // Make this point to the head.
while(curr->next != NULL){ // Loops through until the NULL is found
curr = curr->next;
}
curr->next = n; //Make the currnet node point to N
n->prev = curr; //Make the previous node connect to curr
n->next = tail; // connect new node to the tail.
}
else{
head = n; //If there is no list, this makes N the first node.
}
Here is the class that prototypes the functions to be used.
class PLAYER
{
public: // Functions go inside PUBLIC
PLAYER();
void AddNode(int addID, std::string addName);
void DeleteNode(int delPlayer);
void SortNode();
void PrintList();
void InsertHead(int AddID, std::string addName);
void PrintReverse();
private: //Variables go into here
typedef struct node{
// ...
std::string name;
int ID;
node* next;
node* prev;
}* nodePtr;
nodePtr head, curr, temp, prev, test, tail;
};
And finally my attempt to create a reverse traversing function to print backwards.
void PLAYER::PrintReverse()
{
curr = head;
while(curr->next != NULL) //Get to the end of the list
{
curr = curr->next;
}
while(curr->prev != NULL) //Work backward and print out the contents
{
std::cout << curr->ID << " " << curr->name << endl;
curr = curr->prev;
}
}
What I would like to do is inside the PrintReverse() function have it initialize via the tail pointer, however I can not figure out the functions to add to PrintReverse() and to AddNode() in order to have the new nodes pointed to by tail.
This is my first question posting here, I hope I covered all my bases. Thank you for any help I can find.
EDIT:
Thank you for all your input. I am relearning data structures and yes this is some self imposed homework on my part to begin to get the logic flowing again.
I will make the changes when I get home tonight.
The following changes would need to be considered.
The PrintReverse function would not need the forward pass to obtain the tail.
void PLAYER::PrintReverse()
{
curr = tail;
while(curr != NULL) //Work backward and print out the contents
{
std::cout << curr->ID << " " << curr->name << endl;
curr = curr->prev;
}
}
There is a problem in how tail is handled in the AddNode function. See the lines where the comments contain [CHANGED] and [ADDED]:
if(head != NULL){ // This checks to see if a list is set up.
curr = head; // Make this point to the head.
while(curr->next != NULL){ // Loops through until the NULL is found
curr = curr->next;
}
curr->next = n; //Make the currnet node point to N
n->prev = curr; //Make the previous node connect to curr
n->next = NULL; // [CHANGED]: we want the last node not to have a successor.
}
else{
head = n; //If there is no list, this makes N the first node.
}
tail = n; // [ADDED]: the last node added is the new tail.
However, a simpler solution is to avoid again the forward pass, and start from tail.
if(tail != NULL){ // This checks to see if a list is set up.
tail->next = n; //Make the old tail node point to N
n->prev = tail;
n->next = NULL;
}
else{
head = n; //If there is no list, this makes N the first node.
}
tail = n; // The last node added is the new tail.
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;
}
}
I'm trying to figure out how to clear a stack (in the form of a linked list). Linked lists aren't my forte; I don't understand them at all. Here's my code, can anyone shed some light onto why it's not working? When I try to call the method through a switch in main, it seems too get stuck in an infinite loop.
void stack :: clearStack()
{
if (isEmpty()== true)
{
cout << "\nThere are no elements in the stack. \n";
}
else
{
node *current = top;
node *temp;
while(current != NULL);
{
current = temp -> next;
delete current;
current = temp;
}
}
}
There are a few problems with that code. The first is that you dereference an uninitialized pointer (temp) the other that you delete the next pointer before you loop (and thereby pulling the carpet out under your own feet, so to say).
It's as simple as
node* next;
for (node* current = top; current != nullptr; current = next)
{
next = current->next;
delete current;
}
Oh, and don't forget to clear top when you're done.
You have not initialized temp. You need to set temp to the first node of the list. Inside the loop, cycle through the nodes and keep deleting them.
node *current = top;
node *temp = top; // initialize temp to top
while(current != NULL);
{
temp = temp -> next; // increase temp
delete current;
current = temp;
}
Think this is what you wanted to do:
node *current = top;
while(current != NULL);
{
node *temp = current->next;
delete current;
current = temp;
}
top = null;
if (isEmpty()== true)
{
cout << "\nThere are no elements in the stack. \n";
}
else
{
node *current = top;
node *temp;
while(current != NULL);
{
current = temp -> next;
delete current;
current = temp;
}
}
That whole block can be replaced by:
while (top != nullptr)
{
unique_ptr<node> p(top);
top = top->next;
}
If the list is already empty, nothing is done. If it is non-empty, unique_ptr takes control of the memory management of the current top (which will delete it between loop iterations), move the top to the next. When top is NULL, everything is cleared and top is set to NULL.