Reversing a linked list (by recursion) not working - c++

I was trying to write a code to reverse the linked list but getting wrong output.
Is there something I am missing.
Here is the function
void reverselinklist( struct node **headreverse)
{
struct node *p = *headreverse;
if(p->next == NULL)
{
*headreverse = p;
return;
}
reverselinklist(&(p->next));
p->next->next = p;
p->next = NULL;
}
After display function
Input 409765
Output 4

*headreverse = p is meaningless. You should set *headreverse = p->next each time to move forward, until the last node is reached.
Anyway, I changed your code to make it work:
void reverselinklist(struct node **headreverse)
{
struct node *p = *headreverse;
if(p->next == NULL){
return;
}
*headreverse = p->next;
reverselinklist(headreverse);
p->next->next = p;
p->next = NULL;
}

For single list use two two pointers, to update list as you can not go back.
Here is my code. Hope it will help you to understand concept.
void reverselinklist(struct node** head_ref)
{
struct node* first;
struct node* rest;
first = *head_ref;
rest = first->next;
if (rest == NULL)
return;
reverselinklist(&rest);
first->next->next = first;
first->next = NULL;
*head_ref = rest;
}
If it could me more precise please provide suggestions.

Your headreverse is not being assigned to the new head of the list. Be sure to use 2 arguments for your function, 1) head of the initial list 2) current node(same as your headreverse)
if(p->next == NULL)
{
*head = p; //instead of headreverse use head
return;
}

Related

C++ linked lists using pointers - beginner question

I have been learning C++ for the last couple of months, and after going through an online course I have started doing some challenges with using raw pointers. I have successfully created class that can initiate and iterate through linked list, with lots of struggle I managed to create method that deletes its element(s), but I am struggling to write a method that would remove all the duplicates.
I have a method such as
void linked_list::remove_dups(){
Node *p = first;
Node *g = first;
while(p!=NULL){
int x = 0;
g = new Node;
g = first;
Node *remove = first;
while (g!=NULL){
if(p->data == g->data){
x++;
}
if(x>1){
remove = new Node;
remove = p;
p = p->next;
remove->next = p->next;
delete remove;
x--;
}
g = g->next;
}
p = p->next;
}
}
where Node is standard
struct Node{
int data;
struct Node *next;
};
first is private member
Node *first;
Can anyone point out what is wrong in this function and explain please? I initiated list with pointers that is
int a[] = {3,5,5,7,65,5,65,65,4,4,15};
and it removed most of the duplicates, but not all. If I add more though, I have EXC_BAD_ACCESS error.
Really appreciate any help!
The main issue is:
p = p->next;
remove->next = p->next;
delete remove;
You try to set remove->next to point to the new next element. But remove is going to be deleted. So the element before remove will still point to something deleted. So, after the delete, you'll have a broken list that contains pointer to deleted elements. Next loop iteration, it will break.
Below is the code I edited as I went. Please note that
remove = new Node;
remove = p;
is not only useless, it leaks memory. You can directly do remove = p;
Just draft code as I went. Not fixed. Proper would be keeping a prev pointer or something.
void linked_list::remove_dups()
{
Node *p = first;
Node *g = first;
while(p!=NULL)
{
// int x = 0; remove this
// g = new Node; remove this
g = first;
Node *remove = first;
while (g != NULL)
{
if(p->data == g->data) // test directly, no x
{
// remove = new Node; remove this
remove = p;
p = p->next;
// remove->next = p->next; You are going to delete this, no point modifying it
delete remove;
}
g = g->next;
}
p = p->next;
}
}
Something I wrote for my custom doubly-linked list that will remove duplicates. Not necessarily the most efficient but it gets the job done.
void unique()
{
std::map<int, int> hash;
Node<T>* temp = this->head;
while(temp)
{
hash[temp->data]++;
if(hash[temp->data] > 1)
{
Node<T>* next = temp->next;
Node<T>* prev = temp->prev;
delete temp;
temp = nullptr;
if(!next)
{
temp = prev;
temp->next = nullptr;
hash[temp->data]--;
break;
}
next->prev = prev;
prev->next = next;
temp = next;
hash[temp->data]--;
}
else
{
temp = temp->next;
}
}
}

calling a function within another function

I am making a simple linked list with an insert function that has 4 conditions:
add in the middle of the list
add to the head if the list is not empty
add to an empty list
add to the end of a list
I have made an addNode function that takes care of the last two conditions and im trying to implement it inside of the insertNode but it keeps crashing? is there any specific reason or am I just missing something simple?
addNode:
void linkList::addNode(int dataAdd) // this only adds a node to the end
{
nodePtr n = new node; // what this does is make the node pointer 'n' point to this new node
n->next = NULL;
n->data = dataAdd;
if (head != NULL)
{
follow = head;
while (follow->next != NULL)
{
follow = follow->next;
}
follow->next = n;
}
else
{
head = n;
}
}
insertNode:
void linkList::insertNode(int dataInsert)
{
nodePtr n = new node;
n->next = NULL;
n->data = dataInsert;
follow = head;
while (follow != NULL)
{
trail = follow;
follow = follow->next;
if (head->data < dataInsert){
n->next = head; //n's next will become the current head (n is now the first item in the linkList)
head = n; //n the head structure will now be n (n is the new head)
}
else if (follow->data < dataInsert)
{
trail->next = n;
n->next = follow;
break;
}
else
{
addNode(dataInsert);
}
}
}
I want to call addNode in the else statement in insertNode

Linked List Insertion problems

I'm trying to insert an object (bird) that holds a name and an ID number
I'm having problems inserting the object into my linked list
bool List342::Insert(Bird *obj)
{
Node *insNode = new Node;
insNode->data = obj;
if (head == NULL)
{
head = insNode;
return true;
}
//cout << head->data->getID();
if ((insNode->data->getID()) <= (head->data->getID()))
{
insNode->next = head;
head = insNode;
return true;
}
Node *pNode = head;
while ((pNode->next != NULL) && ((pNode->next)->data->getID() <= insNode->data->getID()))
{
pNode = pNode->next;
}
insNode->next = pNode->next;
pNode->next = insNode;
return true;
}
It doesn't seem to insert correctly
I tried putting a cout code to see what numbers are being compared
for example
cout << head->data->getID()
and it seems to output the current id of the current bird
and not the id of the head (should be the lowest ID)
please and thank you!
I do not see where the function would return false. So I think there is no any sense to declare the function as having return type bool because it always returns true.
I have declared the functtion as having return type void though you may declare the function as having return type bool as before but in this case you need to add last statement that will return true.
Maybe it would be better to declare the function as returning a reference to the list itself.
The function could be defined the following way
void List342::Insert( Bird *bird )
{
Node *prev = NULL;
Node *current = head;
while ( current != NULL && !( bird->getID() < current->data->getID() ) )
{
prev = current;
current = current->next;
}
Node *newnode = new Node { bird, current };
if ( prev != NULL ) prev->next = newnode;
else head = newnode;
}
I suppose that Node has the following definition
struct Node
{
Bird *data;
Node *next;
};
You may substitute statement
Node *newnode = new Node { bird, current };
for
Node *newnode = new Node;
newnode->data = bird;
newnode->next = current;
The function is working fine for me.
I hope, the head is change outside of the insert function.
Shall you check the calling portion of the insert or any other places modifying the head value.

Why wont my Insert function for a list make new nodes?

Hello My problem with this code is on my 2nd else loop; i never enter it and therefore i never make new nodes for my list. can anyone help me see what i am missing?
bool List::Insert(int data)
{
Node* P = new Node;
if(P==NULL)
{
return false;
}
else
{
P ->info = data;
P ->next = NULL;
if(Head == NULL)
{
Head = P;
}
else
{
Node* lastNode;
for(lastNode = Head; lastNode ->next != NULL; lastNode = lastNode ->next)
{
lastNode ->next = P;
}
}
return true;
}
}
This:
Node* lastNode;
for(lastNode = Head; lastNode ->next != NULL; lastNode = lastNode ->next)
{
lastNode ->next = P;
}
is dead wrong. It will change the next pointer, for every single node currently in the list, to point to your new node. You need to only change the pointer in the last node:
Node* lastNode = Head;
while (lastNode->next != NULL)
lastNode = lastNode->next;
lastNode->next = P;
You may also, for efficiency, want to maintain a separate Tail pointer (in addition to your Head) so that you can simply replace that whole operation with:
Tail->next = P;
Tail = P;
That way, you won't have to traverse the entire list every time you want to append a new node. Your code then becomes something like (without the traversal, and with updating the tail pointer as well):
// Prepare new node.
Node *P = new Node;
P->info = data;
P->next = NULL;
// If list empty, set head and tail to new node, otherwise
// append it.
if (Head == NULL) {
Head = P;
Tail = P;
} else {
Tail->next = P;
Tail = P;
}
I'll stop short of criticising the fact that your Insert method doesn't actually insert but rather appends. My near-anal-retentive nitpicking nature is unlikely to endear me to you:-)
lastNode ->next = P; // this must go after the for

Implementing push/pop in a linked list (C++)

I'm trying to incorporate push/pop into a linked list and I can't seem to get it to work. When I run my test function, I set my linked list to zero and I try to push on values but the list keeps getting returned with no values in it. Could anyone possibly tell me what I'm doing wrong?
if (top == NULL){
current = top;
current->next = NULL; //NULL->next : will cause segfault
}
if top is NULL, you set current = top [which is NULL], and then you access current->next, which will cause a segfault, you are trying to access NULL..
EDIT: follow up to comments:
your if statement seems redundant, you should probably only need to set: current->next = head; and head = current; [in addition to the current allocation]
Instead of
if (top == NULL){
current = top;
current->next = NULL;
}
you want
if (top == NULL){
top = current;
current->next = NULL;
}
And of course, after this, you have to make sure that you actually set head to top again.
Now that you've made this change, it should be clear that both cases do the same thing -- so no case distinction is actually necessary. So the function can be simplified to
void push(Data * newPushData){
LinkNode * current = new LinkNode(newPushData);
current->next = head;
head = current;
}
The top variable is local variable for push(...) function. You can use head instead, and I'd rather modify the if statement.
I think that function should look like this:
void push(Data * newPushData){
LinkNode * current = new LinkNode(newPushData);
if (head != NULL){
current->next = head;
head = current;
}
else{
head = current;
current->next = NULL; // if you haven't done it in LinkNode constructor
}
}
can you please specify the attributes of the linked list class ? [ is there slightly chance you are doing something wrong]
Instead of you , I'd do :
void push(Data * newPushData){
if (head == NULL)
head->data = newPushData
tail = head ;
else // regular situation
{
Node * node = new Node() ;
tail->next = node;
node->data = newPushData;
node->next = NULL ;
tail = node ;
}
}
In a linked list you have got to maintain the head pointer point on the head of the list , maintain that the tail pointer is point on the tail of the list ,
You must take care of the 2 cases of enlarging the list.
the best way for learning is to illustrate an insertion on a blank linked list.
Take care
S
void push(Data * newPushData)
{
if( head != NULL )
{
LinkNode current = new LinkNode(newPushData);
current->next = head;
head = current;
}
else
{
head = new LinkNode(newPushData);
}
}
Try this code...
void push(data * newpushdata){
if(head !=null){
linkednode current = new linkednode(newpushdata);
current->next = head;
head = current;
}
else {
head = new linkednode(newpushdata);
}
}
that is my working solution for a Stack containing int elements, but maybe it's better to create a void pushStack using Stack **S instead of Stack *S.
in pop(Stack **S) i created a sentinel, so if the stack is empty -1 is returned.:
typedef struct StackT {
int val;
struct StackT *next;
} Stack;
int isStackEmpty (Stack *S) {
if (S == NULL)
return 1;
else
return 0;
}
int *pop(Stack **S) {
Stack *tmp = *S;
int i = -1;
if (isStackEmpty(tmp) == 0) {
i = tmp->val;
*S = tmp->next;
}
return i;
}
Stack *pushStack (Stack *S, int x) {
Stack *node = (Stack *) malloc (sizeof (Stack));
node->val = x;
node->next = S;
return node;
}
you can call pop and stack easly:
Stack *S = NULL;
int x = somevalue;
int y;
S = pushStack(S, x);
y = pop(&S);