Merge two sorted Linked List - c++

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;
}

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 ++;

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.

How to reverse a singly linked list in 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.

Adding to a Sorted Doubly LinkedList (C++)

I've implemented a program that creates a sorted doubly linked list. Everything works fine except the fact that I can't seem to figure out where program is accepting the node 66 as head, and 44 (which is smaller) as the node after. Here's my add function.
bool SortedDoublyLinkedList<ItemType>::add(const ItemType &newEntry) {
Node<ItemType> *newNode = new Node<ItemType>();
newNode->setItem(newEntry);
if (size == 0) //checks if linked list is empty -> add elements if so.
{
head = newNode;
newNode->setNext(NULL);
newNode->setPrev(NULL);
tail = newNode;
}
// checks if the new node to be added is small than node that head is currently pointing to. If so, add new node before head and make it the new head of list.
else if (newNode->getItem() < head->getItem()) {
head->setPrev(newNode);
newNode->setNext(head);
newNode->setPrev(NULL);
head = newNode;
}
// checks if new node is bigger than the tail node (or last node). If so, add new node to end of list. Then make that new node the tail (end) of list.
else if (newNode->getItem() > tail->getItem()) {
tail->setNext(newNode);
newNode->setNext(NULL);
newNode->setPrev(tail);
tail = newNode;
}
// if the new node is neither of the mentioned situations, add the new node in the correct position in middle of the list. TempPtr1 acts as a ptr and the new node will be added directly in front of it.
else {
Node<ItemType> *tempPtr1;
tempPtr1 = head;
while (newNode->getItem() > tempPtr1->getItem()) {
tempPtr1 = tempPtr1->getNext();
}
newNode->setPrev(tempPtr1->getPrev());
newNode->setNext(tempPtr1); // = tempPtr1;
tempPtr1->getPrev()->setNext(newNode);
tempPtr1->setPrev(newNode);
}
size++;
return true;
}
Output:
66
44
88
88

Linked list copy constructor

I originally had to create my own linked list with using the STL. Now, I am to implement a copy constructor method and I am having real difficulty understanding it. Have a test on this in a few days so I would really like to get it clear. (Test is closed book so need to really).
The List contains a EmployeeNode pointer *head. The EmployeeNode contains an Employee and a pointer to the next EmployeeNode. The Employee class contains a name and salary.
The method seems to get caught in the for loop when trying to copy the 3rd node over. I think this is because I overwrite the newNode but I do not know how to solve this.
ListOfEmployee::ListOfEmployee(const ListOfEmployee &obj)
{
head = NULL;
if(obj.head != NULL)
{
EmployeeNode *newNode = new EmployeeNode("", 0);
EmployeeNode *tempPtr;
EmployeeNode *newPtr;
//using the temp pointer to scroll through the list until it reaches the end
for(tempPtr = obj.head; tempPtr->next !=NULL; tempPtr = tempPtr->next)
{
if(head == NULL)
{
cout<<"Attempts to initialize the head"<<endl;
head = newNode; //assinging the new node to the head
newNode->emp.name = tempPtr->emp.name;
newNode->emp.salary = tempPtr->emp.salary;
cout<<"Initializes the head"<<endl;
}
else
{
cout<<"Attempts to add a new node"<<endl;
//using the temp pointer to scroll through the list until it reaches the end
for(newPtr = head; newPtr->next !=NULL; newPtr = newPtr->next)
{
cout<<"Looping through the list"<<endl;
}
//assiging the last place to the new node
newPtr->next = newNode;
newNode->emp.name = tempPtr->emp.name;
newNode->emp.salary = tempPtr->emp.salary;
cout<<"Adds a new node"<<endl;
}
}
}
}
In your code where you are adding newNode in newPtr->next = newNode; you are basically using previously allocated node. You should create a new node using new. Something like:
newPtr->next = new EmployeeNode("", 0);
newNode = newPtr->next;
newNode->emp.name = tempPtr->emp.name;
newNode->emp.salary = tempPtr->emp.salary;
Also you should set newNode->next = NULL; in your code.