How to pass a pointer from a void function to another C++ - c++

Consider the following piece of code:
void List::insertFront(int key)
{
Node *tmp_node = new Node;
tmp_node->key = key;
tmp_node->next = head->next;
tmp_node->prev = head;
head->next = tmp_node;
_size++;
}
This function adds an element to the beginning of a list and I want to catch the first element of the list in another function and delete it. For this purpose I have written the following piece of code:
bool List::getFront(int &key)
{
if (head->next->key == key)
{
Node *tmp_node = new Node;
head->next = tmp_node->next;
delete tmp_node;
delete head->next;
_size--;
return true;
}
else return false;
}
As you can see each time I am creating a new node which utilizes a fresh empty list, but I want to use the list that was created in the previous function.
How can I pass the node from insertFront() to getFront()?

Your getFront() code is all wrong. You need something more like this instead:
bool List::popFrontIfMatches(int key)
{
Node *tmp_node = head->next;
if ((tmp_node) && (tmp_node->key == key))
{
if (tmp_node->next)
tmp_node->next->prev = tmp_node->prev;
if (tmp_node->prev)
tmp_node->prev->next = tmp_node->next;
head->next = tmp_node->next;
delete tmp_node;
_size--;
return true;
}
else
return false;
}
That being said, why are you treating head->next as the 1st node in the list, and not head itself as is the usual common practice?
void List::insertFront(int key)
{
Node *tmp_node = new Node;
tmp_node->key = key;
tmp_node->next = head;
tmp_node->prev = NULL;
head = tmp_node;
_size++;
}
bool List::popFrontIfMatches(int key)
{
Node *tmp_node = head;
if ((tmp_node) && (tmp_node->key == key))
{
if (tmp_node->next)
tmp_node->next->prev = tmp_node->prev;
if (tmp_node->prev)
tmp_node->prev->next = tmp_node->next;
head = tmp_node->next;
delete tmp_node;
_size--;
return true;
}
else
return false;
}

Related

C++ Need help on Remove Node function

I have stressed my head out the last few days to figure out how to get this remove() function to work. I'm still a student and data structure is no joke.
I really need help on how to get this function to remove a specific number on the list from user input. Doesn't matter what I try, it still could not work right.
For example, the list is: [1, 2, 3]
I want to delete number 2 on the list. I want the remove() function to traverse thur the list, if it found number 2, then delete number 2.
class SortedNumberList {
public:
Node* head;
Node* tail;
SortedNumberList() {
head = nullptr;
tail = nullptr;
}
void Insert(double number) {
Node* newNode = new Node(number);
if (head == nullptr) {
head = newNode;
tail = newNode;
}
else {
tail->SetNext(newNode);
tail = newNode;
}
}
// Removes the node with the specified number value from the list. Returns
// true if the node is found and removed, false otherwise.
bool Remove(double number) {
Node* temp = head;
if (temp == nullptr) {
return false;
}
if (head->GetData() == number) {
head = head->GetNext();
return true;
}
else{
while (temp != nullptr) {
Node* curNode = temp;
Node* preNode = nullptr;
preNode = curNode->GetPrevious();
temp = temp->GetNext();
if (curNode->GetData() == number) {
preNode = curNode->GetNext();
return true;
}
delete curNode;
}
}
delete temp;
}
};
class Node {
protected:
double data;
Node* next;
Node* previous;
public:
Node(double initialData) {
data = initialData;
next = nullptr;
previous = nullptr;
}
Node(double initialData, Node* nextNode, Node* previousNode) {
data = initialData;
next = nextNode;
previous = previousNode;
}
Edit: I'm able to solve my own issue, thank you everyone.
bool Remove(double number) {
// Your code here (remove placeholder line below)
Node* temp = head; //Make a temporary node point to head.
if (temp == nullptr || head == nullptr) { //if user don't provide input, return false.
return false;
}
if (head->GetData() == number) { //If number need to delete is at head.
head = head->GetNext();
return true;
}
else {
while (temp != nullptr) { //Travese temp node throught out a list.
Node* curNode = temp->GetNext(); //Make a current node point at temp next.
Node* preNode = temp;
Node* sucNode = curNode->GetNext();
if(curNode->GetData() == number) { //Delete a node if number is found on the list
if (curNode->GetNext() == nullptr) { //Delete at tail.
preNode->SetNext(nullptr);
tail = preNode;
delete curNode;
return true;
}
if (curNode->GetNext() != nullptr) {
preNode->SetNext(sucNode);
sucNode->SetPrevious(preNode);
delete curNode;
return true;
}
}
temp = temp->GetNext();
}
}
return false;
}
};
You should make Node a friend class of SortedNumberList or define former inside the later class which simplifies the code somewhat. It's personal preference but it leads to less unnecessary boilerplate code (getters and setters).
In a double linked list you do not need to keep track of the last as you do need on single linked lists because you have both pointers available.
The quest is just a matter of iterating to find the value, taking care to cut it early when we pass the mark since it is a sorted list.
Then delete the object and update the link pointers.
bool Remove(double number) {
// Loop through the entire list
Node* temp = head;
while ( temp != nullptr) {
// There is no point looking forward if the list is sorted
if (temp->data > number ) return false;
// Compare to find
if (temp->data == number) {
// Get the pointers so we can delete the object
Node* prev = temp->previous;
Node* next = temp->next;
// Delete object
delete temp;
// Update previous pointers
if ( prev==nullptr ) {
head = next;
} else {
prev->next = next;
}
// Update next pointers
if ( next==nullptr ) {
tail = prev;
} else {
next->previous = prev;
}
// Indicate success
return true;
}
}
// We iterated to the end and did not find it
return false;
}

How to insert a node in a linked list after a given index

I am trying to insert a node at a both given index in a linked list and just at the end, but I don't understand the syntax or even conceptually what I am doing.
I have an insertTail function and an insertAfter function for both of these problems, but I'm not sure I am implementing them correctly.
void insertTail(T value) {
if (head == NULL) {
insertHead(value);
}
else {
T tailNode = Node(value);
Node* tempPtr = head;
while (tempPtr != NULL) {
tempPtr = tempPtr->next;
}
next = tailNode->data;
}
};
void insertAfter(T value, T insertionNode) {
Node* tempPtr = head;
while (tempPtr->data != insertionNode) {
tempPtr = tempPtr->next;
}
Node* afterNode = new Node(value);
afterNode->next = tempPtr->next;
tempPtr->next = afterNode;
};
My code won't even compile with what I have currently. It gives an error for the first line in the else statement in the insertTail function that reads
'initializing': cannot convert from 'LinkedList<std::string>::Node' to 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>'
Both of your functions are implemented all wrong. They need to look more like this instead (assuming a single-linked list is being used):
void insertTail(T value) {
if (!head) {
insertHead(value);
}
else {
Node* tailNode = head;
while (tailNode->next) {
tailNode = tailNode->next;
}
tailNode->next = new Node(value);
}
}
void insertAfter(T value, Node *insertionNode) {
if (!insertionNode) {
insertTail(value);
}
else {
Node* newNode = new Node(value);
newNode->next = insertionNode->next;
insertionNode->next = newNode;
}
}

Remove node from a linked list

I have been stuck on this function to remove node from a list, if there are two names in the list they are both gone. If Anne and John are in the list and I want to delete Anne, then my list is empty, John is gone.
What am I missing to keep the connection in the list if I delete a node init?
bool ContactList::remove(string key)
{
NodePtr prev = NULL;
for(NodePtr temp = head; temp != NULL; temp = temp->link)
{
if(temp->data.key == key)
{
if(prev == NULL)
{
head = temp->link;
delete temp;
return true;
}
else
{
prev = temp->link;
delete temp;
return true;
}
}
}
return false;
}
You aren't keeping prev up to date in every iteration of your loop. You want something like:
prev = temp;
at the bottom of your for loop.
Try using this function
bool ContactList::remove(string key)
{
NodePtr prev = NULL;
for(NodePtr temp = head; temp != NULL; temp = temp->link)
{
if(temp->data.key == key)
{
if(prev == NULL)
{
head = temp->link;
delete temp;
return true;
}
else
{
prev->link = temp->link; // change.
delete temp;
return true;
}
}
prev = temp; // change.
}
return false;
}

Recursive Reverse Single Linked List

I am trying to just write a basic function that reverses a singly-linked list which is recursive. I was wondering if i tackled this in the right approach? Maybe someone can give me some pointers.
void reverse(Node*& p) {
if (!p) return;
Node* rest = p->next;
if (!rest) return;
reverse(rest);
p->next->next = p;
p->next = NULL;
p = rest;
}
That's not the most efficient way, but to do it, you can call the reverse method with the "next" pointer until there is no next. Once there, set next to previous. After returning from the recursion, set next to previous. See the recursive version here for an example. From the link:
Node * reverse( Node * ptr , Node * previous)
{
Node * temp;
if(ptr->next == NULL) {
ptr->next = previous;
previous->next = NULL;
return ptr;
} else {
temp = reverse(ptr->next, ptr);
ptr->next = previous;
return temp;
}
}
reversedHead = reverse(head, NULL);
This might be helpful
List
{
public:
.....
void plzReverse()
{
Node* node = myReverse(head);
node->next = NULL;
}
private:
Node * myReverse(Node * node)
{
if(node->next == NULL)
{
head = node;
return node;
}
else
{
Node * temp = myReverse(node->next);
temp ->next = node;
return node;
}
}
}
Another solution might be:
List
{
public:
.....
void plzReverse()
{
Node* node = myReverse(head, head);
node->next = NULL;
}
private:
Node * myReverse(Node * node, Node*& rhead)
{
if(node->next == NULL)
{
rhead = node;
return node;
}
else
{
Node * temp = myReverse(node->next,rhead);
temp ->next = node;
return node;
}
}
}
This is what you need:
Node* reverse(Node* p) {
if (p->next == NULL) {
return p;
} else {
Node* t = reverse(p->next); // Now p->next is reversed, t is the new head.
p->next->next = p; // p->next is the current tail, so p becomes the new tail.
p->next = NULL;
return t;
}
}
The recursive solution can look quite pretty, even in C++:
Node* reverse(Node* pivot, Node* backward = 0) {
if (pivot == 0) // We're done
return backward;
// flip the head of pivot from forward to backward
Node* rest = pivot->next;
pivot->next = backward;
// and continue
return reverse(rest, pivot);
}
Most C++ compilers do tail call optimization so there's no reason to believe this to be less efficient than an iterative solution.
Here is the solution that preserves return value as void.
void reverse(Node*& p) {
if (!p) return;
Node* rest = p->next;
if (!rest) {
rest = p;
return;
}
reverse(rest);
p->next->next = p;
p->next = NULL;
p = rest;
}
linkedList *reverseMyNextPointer(linkedList *prevNode, linkedList *currNode)
{
linkedList *tempPtr;
if(!currNode)
return prevNode;
else
{
tempPtr = currNode->next;
currNode->next = prevNode;
return reverseMyNext(currNode,tempPtr);
}
}
head = reverseMyNextPointer(nullptr,head);

Crash, while printing contents of linked-list

I'm having some trouble printing out the contents of a linked list. I'm using an example code that I found somewhere. I did edit it a bit, but I don't think that's why it's crashing.
class stringlist
{
struct node
{
std::string data;
node* next;
};
node* head;
node* tail;
public:
BOOLEAN append(std::string newdata)
{
if (head)
{
tail->next = new node;
if (tail->next != NULL)
{
tail=tail->next;
tail->data = newdata;
return TRUE;
}
else
return FALSE;
}
else
{
head = new node;
if (head != NULL)
{
tail = head;
head->data = newdata;
return TRUE;
}
else
return FALSE;
}
}
BOOLEAN clear(std::string deldata)
{
node* temp1 = head;
node* temp2 = NULL;
BOOLEAN result = FALSE;
while (temp1 != NULL)
{
if (temp1->data == deldata)
{
if (temp1 == head)
head=temp1->next;
if (temp1==tail)
tail = temp2;
if (temp2 != NULL)
temp2->next = temp1->next;
delete temp1;
if (temp2 == NULL)
temp1 = head;
else
temp1 = temp2->next;
result = TRUE;
}
else // temp1->data != deldata
{
temp2 = temp1;
temp1 = temp1->next;
}
}
return result;
}
BOOLEAN exists(std::string finddata)
{
node* temp = head;
BOOLEAN found = FALSE;
while (temp != NULL && !found)
{
if (temp->data == finddata)
found=true;
else
temp = temp->next;
}
return found;
}
void print()
{
node* tmp = head;
while (tmp)
{
printf("%s", tmp->data.c_str());
tmp = tmp->next;
}
}
stringlist()
{
head=NULL;
tail=NULL;
}
};
My main() function is really simple:
int main()
{
stringlist mylist;
if (mylist.append("something"))
count++;
if (mylist.append("else"))
count++;
if (mylist.append("yet"))
count++;
cout<<"Added "<<count<<" items\n";
mylist.print();
return 0;
}
For some reason in Print() tmp is never NULL
in node, add a constructor to initialize next to null
As #rmn pointed out, you're not initializing the value of node->next.
BOOLEAN append(std::string newdata)
{
if (head)
{
tail->next = new node;
if (tail->next != NULL)
{
tail=tail->next;
tail->data = newdata;
tail->next = NULL; // <- this is the part that is missing
return TRUE;
}
else
return FALSE;
}
else
{
head = new node;
if (head != NULL)
{
tail = head;
head->data = newdata;
head->next = NULL; // <- it's also missing here.
return TRUE;
}
else
return FALSE;
}
}
You could solve this by having a default constructor for node:
struct node
{
std::string data;
node* next;
node() : next(NULL) { }
};
With the default constructor you won't need to add tail->next = NULL;.
You aren't initializing head->tail appropriately in append when head==NULL initially.
Correct. That's because tail is only NULL in your code when the linked list is initially created. After you add a node, you set tail = head, and from that point in time, every time you add an element, you set tail->next = new node, and then tail = tail->next... so that tail->next always = tail.