How to reverse a singly linked list in C++? - c++

I am trying to reverse a single linked list with this code but its not working properly.The following code not works in that case when the size of list is two otherwise it works well.I cannot find error in this code and spent a lot of time on it.Please tell me whats wrong with this code?
void list::reverse()
{
node *current = head;
if (current->next != NULL)
{
node *move = current->next;
while (move->next != NULL)
{
node *temp = move->next;
move->next = current;
if (current == head)
{
current->next = NULL;
}
current = move;
move = temp;
}
if (move->next == NULL)
{
move->next = current;
if (current == head)
{
current->next == NULL;
}
head = move;
}
}
}

You have:
A (== head) -> B -> C -> D
You want (?):
D (== head) -> C -> B -> A
I got lost in your algorithm completely, can't figure out how it would work, or how to fix it easily. Actually I have hard time to believe it works for longer lists. But too lazy to try.
Maybe try to understand this one (in pseudo C++), looks simpler to me?:
src = head;
reversed = nullptr;
while (nullptr != src) {
// node to insert at the beginning of reversed list
to_prepend = src;
// iterate trough all nodes in normal direction
src = src->next;
// now insert the currently read node at the head of reversed list
to_prepend->next = reversed;
reversed = to_prepend;
}
head = reversed;
I didn't wrote code+debug, so can't guarantee correctness, but it should work like this:
A (== head) -> B -> C -> D
current: A, reversed null, current updated to B (A->B), A->reversed(nullptr), reversed=A
current: B, reversed A, current to C (B->C), B->reversed(A), reversed=B
current: C, reversed B->A, current to D, C->reversed(B), reversed=C
current: D, reversed C->B->A, current to nullptr, D->reversed(C), reversed=D
current: nullptr: exit while
head = reversed (= D->C->B->A->nullptr).
Also in your code the:
current->next == NULL; is boolean expression, throwing the result away, not doing anything.

Related

Adding a node to the beginning of a double-linked list

I am trying to create a function that adds a node to the beginning of a double-linked list in C++, and I'm getting this error in Xcode. I know it must be because I lost the address of one of my temp nodes, but I cannot figure out how to fix it.
template<typename Item>
void DLList<Item>::push_front(const Item &item) {
/* Adds item to a new Node at the front of the list. Updates head,
tail, and size accordingly. Must appropriately handle cases in which the list is empty */
Node*p = new Node;
p -> item = item;
Node*oldHead = head;
p -> next = oldHead;
oldHead -> prev = p; /*error message: Thread 1: EXC_BAD_ACCESS (code=1, address=0x10)*/
head = p;
size ++;
}
The error will happen when oldHead is nullptr, and then oldHead->prev is an invalid access. This happens when the list is empty (head is nullptr).
It is easy to fix: just make sure you only execute that statement when the list is not empty. NB: you don't actually need oldHead. Just keep working with head.
And as the comment in your code seems to suggest your list has a tail member, you should set it when the first node is added to the list:
Node* p = new Node;
p -> item = item;
p -> next = head;
if (head != nullptr) {
head -> prev = p;
} else {
tail = p;
}
head = p;
size ++;

Reverse a linked list using only 2 pointers using XOR operation

I found this code online for reversing a linked list using only 2 pointers using xor operation :
void reverse(struct Node** head_ref)
{
struct Node* prev = NULL;
struct Node* current = *head_ref;
// at last prev points to new head
while (current != NULL) {
current = (struct Node*)((ut)prev ^ (ut)current ^ (ut)(current->next) ^ (ut)(current->next = prev) ^ (ut)(prev = current));
}
*head_ref = prev;
}
Can you please explain how this code works ?
Have you read this: Iteratively Reverse a linked list using only 2 pointers?
while (current != NULL) {
// This expression evaluates from left to right
// current->next = prev, changes the link fron
// next to prev node
// prev = current, moves prev to current node for
// next reversal of node
// This example of list will clear it more 1->2->3->4
// initially prev = 1, current = 2
// Final expression will be current = 1^2^3^2^1,
// as we know that bitwise XOR of two same
// numbers will always be 0 i.e; 1^1 = 2^2 = 0
// After the evaluation of expression current = 3 that
// means it has been moved by one node from its
// previous position
current = (struct Node*)((ut)prev ^ (ut)current ^ (ut)(current->next) ^ (ut)(current->next = prev) ^ (ut)(prev = current));
}

Duplicating linked list to be sorted is deleting the original linked list

I am trying to sort my linked list based on salary so that it displays the highest salary at the top and so on. It parses through my original linked list and duplicates each node to be inserted into a new sorted linked list, in this case "head" is the head of my original and "sorthead" is the head of the duplicate.
static void sortingRecords2() {
EmployeeRecords * q = head;
while (q != NULL) {
EmployeeRecords * sortnode = NULL;
sortnode = q;
sortnode->next = NULL;
sortnode->prev = NULL;
if (sorthead == NULL) {
sorthead = sorttail = sortnode;
}
else if (sortnode->Salary >= sorthead->Salary) {
sortnode->next = sorthead;
sorthead->prev = sortnode;
sorthead = sortnode;
}
else {
temp2 = sorthead;
EmployeeRecords * previous = NULL;
while (temp2 != NULL) {
if (sortnode->Salary <= temp2->Salary) {
previous = temp2;
}
temp2 = temp2->next;
}
if (previous->next == NULL) {
sortnode->prev = sorttail;
sorttail->next = sortnode;
sorttail = sortnode;
}
else {
sortnode->next = previous->next;
sortnode->prev = previous;
previous->next = sortnode;
sortnode->next->prev = sortnode;
}
}
q = q->next;
}
displayRecords(head);
}
After testing out different methods to try and figure out where exactly is the problem, I've determined that the sorting algorithm works fine but after it is done executing and I call my display function it only displays the head of my original list. After executing this function, all other calls to my display function also only displays the head of my original list where previously it properly displays the whole list.
I'm not sure why exactly my main "head" is affected during execution when at the start I already used a temp value "q" to copy the head.
The immediate bug that jumps out at me is
sortnode = q;
is an assignment of addresses. sortnode and q now point at the same node. That means
sortnode->next = NULL;
sortnode->prev = NULL;
changes this shared node and blows the stuffing out of the source list, leaking all of the following nodes.
You will need to create a new node that is a copy of *q for sortnode to point at and build the sorted list with copies of the source nodes.
sortnode = new EmployeeRecords(*q);
is the start of a possible solution.

Binary Tree level order insertion c++

I want to insert in the tree but not using any other data structures like queue. I want to insert in level order and no matter what I code, it doesn't. Also I couldn't find any code without queues or things like that.
Here is my attempt;
void insert(int x) {
if (root == NULL) {
root = new node(x, NULL, NULL);
return;
}
node *temp = root;
node *prev = root;
while (temp != NULL) {
if (temp->left != NULL) {
prev = temp;
temp = temp->left;
} else if (temp->right != NULL) {
prev = temp;
temp = temp->right;
}
}
if (temp->left == NULL)
prev->left = new node(x, NULL, NULL);
else if (temp->right == NULL)
prev->right = new node(x, NULL, NULL);
}
I don't have a link for recursive insertion but it should work like this:
bool recursion(node * current_node, node * to_insert, int &max_depth, int cur_depth) {
if(max_depth < cur_depth) {
max_depth = cur_depth;
}
for (auto & current_child : {current_node->left, current_node->right})
if(current_child == NULL) {
if( max_depth > cur_depth ) {
current_child -> left = to_insert;
return true;
}
} else {
if(recursion(current_child, to_insert, max_depth, cur_depth + 1)) {
return true;
}
}
return false;
}
This does depth-first-search (not breadth-first, I was mistaken above, they are very similar in trees) from left to right. So we will first find the left-most leaf, then the one right next to it and so on. We will always track how deep we are in the tree. If at one point we find a node on the second deepest layer that hasn't got a child, it will add the node we want to insert at this point and recurse up the tree. Due to the order in which we traverse the tree, this will find the left most open spot, so exactly what you want.
This method can return false if the submost layer of the tree is full. Then we have to go down to the left-most leaf and insert the node at its left child. One can also save this leaf somehow when we first find it, but that seemed more complicate to me then just searching it again (this can be done without problem in a for-loop).
You can replace the recursive method by an iteration with a stack (there are many sources on the internet explaining how to make a recursive depth-first-search to a iterative one).
I don't really like the in-out-parameter max_depth but it was the easiest to do this.

Merge two sorted Linked List

I had a doubt in this problem: link I am following this solution:
if((headA==NULL)&&(headB==NULL)
return NULL;
if((headA!=NULL)&&(headB==NULL))
return headA;
if((headA == NULL)&&(headB!=NULL))
return headB;
if(headA->data < headB->data)
headA->next = MergeLists(headA->next, headB);
else if(headA->data > headB->data)
{
Node* temp = headB;
headB = headB->next;
temp->next = headA;
headA = temp;
headA->next = MergeLists(headA->next, headB);
}
return headA;
I get that when headA->data < headB->data then we simply move the headA pointer to the next node. But when headA->data > headB->data, then we create a temp pointer, point it where headA is pointing and move headB to next node. What I don't get is:
How are the nodes which are previously sorted get linked to this new temp node that I have created? Can you please point it out on my code
Also, where is headA pointer pointing to after the second condition? Is it pointing at the new node?
The code effectively moves the head element from list B to list A.
Node* temp = headB;
headB = headB->next;
temp is pointing at the list B head, and headB is pointing at the list B tail. In effect, the list B head has been popped off the list.
temp->next = headA;
The list A is now appended to the popped head.
headA = temp;
And list A is now set to the list with the original head from list B followed by the original list A.
The merge then proceeds exactly as if list A had the smaller head, which it now does because the next element in list B cannot be smaller than it.
This code fails to handle the case that both lists have the same head data value. In that case, it just returns list A without merging the tails.
Not sure why you can't just do this for the last two cases:
if(headA->data < headB->data) {
headA->next = MergeLists(headA->next, headB);
return headA;
}
else {
headB->next = MergeLists(headA, headB->next);
return headB;
}
And keep it simple and symmetric.
You can also simplify the first three cases to the following two:
if(headA == NULL)
return headB;
if(headB == NULL)
return headA;
This can also be done without recursion:
Node *merge_lists(Node *headA, Node *headB)
{
Node *head;
Node **nextPtr = &head;
while (headA && headB) {
Node **headMin = (headA->data < headB->data) ? &headA : &headB;
*nextPtr = *headMin;
nextPtr = &(*headMin)->next;
*headMin = *nextPtr;
}
*nextPtr = headA ? headA : headB;
return head;
}