How to merge 2 linked lists into 1? - list

I have tried to find an answer but couldn't find a clear explenation.
i have the following code:
slist* mergeLists(slist *List1,slist *List2)
{
slist *temp=*List1;
while (temp->next!=NULL)
temp=temp->next;
temp->next=List2;
return List1;
}
I Try to merge List1 with List2 and return List 1 (List 1->List 2).
but i have no idea how o continue.
Thank you

A search in my bookmarks yields this link, which previously helped me achive the merging of two lists. What this basically does is
Node *nodeC; // The combined list
while(nodeA != null && nodeB != null)
{
if(nodeA->Id <= nodeB->Id) // Sorting
{
nodeC->Link = nodeA; // Set nodeA to the link of the current node
nodeC = nodeA; // Set nodeC to nodeA (which is now the current node)
nodeA = nodeA->link;
}
else
{
nodeC->Link = nodeB;
noceC = nodeB;
nodeB = nodeB->Link;
}
}

Related

How these 2 algorithms' outputs are different from each other in a linked list data structure

I have created a Linked-List data structure as follows:
class Node<T> {
T value;
Node<T>? nextNode;
Node({required this.value, this.nextNode});
#override
String toString() {
if (nextNode == null) return '$value';
return '$value --> ${nextNode.toString()}';
}
}
Then create a LinkedList class that holds a head and tail node, and by printing the head, we can see the list of values.
class LinkedList<E> {
Node<E>? head;
Node<E>? tail;
bool get isEmpty => head == null;
// To add a node in front of the list
void push(E value) {
if (isEmpty) {
head = Node(value: value);
tail = head;
return;
}
head = Node(value: value, nextNode: head);
}
// To add a node behind the list
void append(E value) {
if (isEmpty) {
push(value);
return;
}
tail!.nextNode = Node(value: value);
tail = tail!.nextNode; //* variation 1
// tail = Node(value: value); //** variation 2
}
#override
String toString() {
return head.toString();
}
}
As you can see in the comments we could create 2 variations of the append algorithm.
The first one has tail = tail!.nextNode; and the second one has tail = Node(value: value); line.
The first variation works as we expected which means when we print the list it prints correctly as you can see here:
void main() {
final list = LinkedList<int>();
print(list); // output: 'Empty List'
list.append(1);
list.append(2);
list.append(3);
list.append(4);
print(list); // output : 1 --> 2 --> 3 --> 4
}
But with the second variation algorithm we have :
void main() {
final list = LinkedList<int>();
print(list); // output: 'Empty List'
list.append(1);
list.append(2);
list.append(3);
list.append(4);
print(list); // output : 1 --> 2
}
Why is the output different for the second algorithm?
Let's discuss the second algorithm step by step using your example.
list.append(1): Since the list is empty, a new head node is created.
list.append(2): A new node is created (let's say N2).
tail!.nextNode = Node(value: value); means that head.next points to N2.
However, when you do tail = Node(value: value), tail now points to an entirely new node, whereas head.next still points to N2.
list.append(3): Subsequent append calls will not add any new nodes to the original linked list, since the tail pointer is pointing to a arbitrary node which isn't connected to the original list.

Selection sort in single linked list without using swap

I have been trying to solve the selection sort in single linked list without using swap nodes. Using a temp list to store nodes and assign the current list with a new one
//my addlastnode function
void AddLastNODE(LIST &mylist, NODE *p)
{
//Check the list is empty or not
if(isEmpty(mylist))
mylist.pHead = mylist.pTail = p;
else
mylist.pTail->pNext = p;
mylist.pTail = p;
}
void selectionSort(LIST &mylist)
{
//Initialize a temp list to store nodes
LIST mylisttemp;
IntList(mylisttemp);
//Create node
NODE *p;
NODE *i;
//Create min node
NODE *min;
//Check if list is empty or has one node
if(mylist.pHead == mylist.pTail)
return;
//Traverse the list till the last node
for(p=mylist.pHead; p->pNext!=NULL && p!=NULL; p = p->pNext)
{
min=p;
for(i=p->pNext; i!=NULL;i=i->pNext)
{
////Find the smallest data in list
if(i->data < min->data)
min=i;
}
////Add the smallest to a new list
AddLastNODE(mylisttemp, min);
}
//Fill the current list to the new list
if(!isEmpty(mylisttemp))
mylist = mylisttemp;
}
Your code does not reduce the list you are selecting nodes from: the selected node should be removed from it. To make that happen, you need a reference to the node before the selected node, so that you can rewire the list to exclude that selected node.
There is also a small issue in your AddLastNODE function: it does not force the tail node to have a null as pNext pointer. This may be a cause of errors when the function is called with a node that still has a non-null pNext pointer. Secondly, the indentation is off around the else block. It does not lead to a bug in this case, but still it is better to avoid the confusion:
void AddLastNODE(LIST &mylist, NODE *p)
{
if(isEmpty(mylist))
mylist.pHead = p;
else
mylist.pTail->pNext = p;
mylist.pTail = p; // indentation!
p->pNext = nullptr; // <--- better safe than sorry!
}
Then to the main algorithm. It is quite tedious to work with a previous node reference when looking for the node with the minimum value. It helps a bit when you temporarily make the input list cyclic:
void selectionSort(LIST &mylist) {
if (mylist.pHead == mylist.pTail) return;
// Make list temporarily cyclic
mylist.pTail->pNext = mylist.pHead;
LIST mytemplist;
IntList(mytemplist);
while (mylist.pHead != mylist.pTail) {
// Select node:
NODE * beforemin = mylist.pTail;
for (NODE * prev = mylist.pHead; prev != mylist.pTail; prev = prev->pNext) {
if (prev->pNext->data < beforemin->pNext->data) {
beforemin = prev;
}
}
NODE * min = beforemin->pNext;
// Extract selected node:
if (min == mylist.pTail) mylist.pTail = beforemin;
if (min == mylist.pHead) mylist.pHead = min->pNext;
beforemin->pNext = min->pNext;
// And insert it:
AddLastNODE(mytemplist, min);
}
// Move last remaining node
AddLastNODE(mytemplist, mylist.pHead);
// Copy back
mylist = mytemplist;
}
As a side note: You might even want to always keep your list cyclic. This will mean some changes in other functions you may have, as there will be no pNext pointers that are null then.

How to compare 2 linked lists in c++ and put matching data into another linked list

I want to compare two linked lists that contain book titles and then create a new linked list that only has the matching titles from the original lists. Currently I have already created both linked lists and can output both in alphabetical order. The problem comes when I try to compare and create the updated list with the matching titles.
I have tried to create a recursive function that takes in both lists as parameters and will call itself and move the second list to the next node if the titles don't match.
If they both match, then it again calls itself, but moves both lists up a node.
I'm still pretty new on using linked lists and recursion, but I feel like I'm on the right track. All of my other functions are working, I'm just not sure how to make this work and also how to call it in my main function.
Node *compare(Node *h, Node *j) {
Node* h_curr = h;
Node* j_curr = j;
Node* new_node;
Node* updated_list = NULL;
while ((h_curr->next != NULL) || (j_curr->next != NULL)) {
if (h_curr->data != j_curr->data) { // if not equal, then move j_head to the next link
compare(h_curr, j_curr->next);
//j_curr = j_curr->next;
}
else {
updated_list->data = h_curr->data;
new_node = newNode(updated_list->data);
return updated_list;
updated_list = updated_list->next;
compare(h->next, j->next);
}
}
return NULL;
}
#include<string>
#include<iostream>
//assumed node structure
struct Node{
Node(std::string str, Node* ptr = nullptr):data(str), next(ptr){}
std::string data{};
Node* next{};
};
//The following is your rucresive function
void compare(Node* & first, Node* & second, Node* & match) {
if(!first || !second ) return;//base case
if ( first -> data < second -> data) compare(first -> next, second, match );
else if ( first -> data > second -> data) compare(first , second -> next, match);
else{//match found
match = new Node{ first -> data};
compare(first , second -> next, match -> next);
}
}
//To disply the result (recursive function)
void display(Node* & root){
if(!root) return;
std::cout<<root->data<<" ";
display( root-> next);
}
//To test
int main(){
Node* first = new Node{"aaa"};
first->next=new Node{"ccc"};
first->next->next=new Node{"ccc1"};
first->next->next->next=new Node{"ccc3"};
first->next->next->next->next=new Node{"ccc4"};
first->next->next->next->next->next=new Node{"ddd"};
Node* second = new Node{"baaa"};
second->next=new Node{"ccc"};
second->next->next=new Node{"ccc1"};
second->next->next->next=new Node{"ccc2"};
second->next->next->next->next=new Node{"ccc4"};
Node* res;
compare(first, second, res);
display(res);
}

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

Interview Coding - Take a pointer to a Node structure as a parameter and return a complete copy of the passed-in data structure

This is an interview question that I found interesting.
Write a method that takes a pointer to a Node structure as a parameter and returns a complete copy of the passed-in data structure.
The Node structure contains two pointers to other Node structures.
For example, the method signature could look like so:
Node* Copy(Node* root);
Note - Do not make any assumptions about the data structure – it could be a tree, linked list, graph, etc.
How can this be done for any data structure ?
In the generic graph case, you need a mapping from nodes in the original graph to nodes in the new graph, so that when a cycle is encountered, the proper link gets created. If you happen to have extra temporary space in each node, large enough to hold a pointer, then you can store the mapping directly in the nodes; otherwise, you'll need to use an external map, such as an associative array or hash table.
Then it's just a matter of traversing the graph, copying nodes, and looking up the corresponding edges. Something like this:
struct Node
{
Node(int _data) : data(_data) { memset(links, 0, sizeof(links)); }
int data;
Node *links[2];
}
Node *Copy(Node *root)
{
typedef std::map<Node*, Node*> NodeMap;
NodeMap nodeMap;
std::deque<Node*> nodesToVisit;
// Set up initial new root and mapping for the root
Node *newRoot = new Node(root->data);
nodeMap[root] = newRoot;
// Breadth-first search the graph
nodesToVisit.push_back(root);
while(!nodesToVisit.empty())
{
Node *cur = nodesToVisit.front();
nodesToVisit.pop_front();
Node *newCur = nodeMap[cur];
for(int i = 0; i < 2; i++)
{
Node *link = cur->links[i];
if(link)
{
// If we've already created the corresponding node for this
// link, use that. Otherwise, create it and add it to the map.
NodeMap::iterator mappedLink = nodeMap.find(link);
if(mappedLink != nodeMap.end())
{
newCur->links[i] = mappedLink->second;
}
else
{
Node *newLink = new Node(link->data);
nodeMap[link] = newLink;
newCur->links[i] = newLink;
nodesToVisit.push_back(link);
}
}
}
}
return newRoot;
}
The problem as stated is impossible. You have to assume that the entire data structure is stored entirely within the content of nodes that are accessible from that initial one. But that is not an assumption you are allowed to make. Even your standard basic double linked list might not fit that description.
class Copier {
std::map <Node*, Node*> copies;
Node* Copy(Node* n) {
if (!n) return 0;
Node*& copy = copies[n];
if (!copy) {
copy = new Node();
copy.node1 = Copy(n.node1);
copy.node2 = Copy(n.node2);
}
return copy;
}
}
Node* Copy(Node* root) {
if (root == NULL)
return root;
std::unordered_map<Node*, Node*> completed;
std::deque<Node*> todo;
Node *ret = new Node(*scur);
completed.push_back(std::make_pair(root, ret));
todo.push_pack(root);
//while there's more nodes to duplicate
do {
//duplicate the node
Node* oldNode = todo.back();
Node* newNode = completed[cur];
todo.pop_back();
if(oldNode->left) {
auto iter = completed.find(oldNode->left);
//if it has a left child that needs duplicating, add it to the todo list
if (iter == completed.end()) {
newNode->left = new Node(*(oldNode->left));
completed.push_back(std::make_pair(oldNode->left, newNode->left));
todo.push_back(oldNode->left);
} else {
newNode->left = completed[oldNode->left];
}
}
if(oldNode->right) {
auto iter = completed.find(oldNode->right);
//if it has a right child that needs duplicating, add it to the todo list
if (iter == completed.end()) {
newNode->right = new Node(*(oldNode->right));
completed.push_back(std::make_pair(oldNode->right, newNode->right));
todo.push_back(oldNode->right);
} else {
newNode->right= completed[oldNode->right];
}
}
} while(todo.empty() == false)
//return the translation of the root
return ret;
}
Doesn't have stack overflow, root can be NULL, doesn't fail if left or right are NULL.
[Edit]Adam Rosenfield made me realize this was incorrect if there was loops in the network. Had to rewrite almost from scratch. Due to the large amount of code required, I prefer his code's for loop.
return new Node(*node);
Trick question?
You should write it recursively;
Node * Copy( Node * root )
{
Node * node_copy;
node_copy = new Node; // Assume Node1 and Node2 are initialized to 0
node_copy->content = root->content;
if( root->Node1 ) node_copy->Node1 = Copy( root->Node1 );
if( root->Node2 ) node_copy->Node2 = Copy( root->Node2 );
return node_copy;
}
So, this does not make any assumption on the data type
Given that a copy constructor exists that copies only the contents of a node and not its children:
Node* Copy(Node* root)
{
Node* copy = new Node(*root);
copy->left = Copy(root->left);
copy->right = Copy(root->right);
return copy;
}
In a more general sense, I would use copy-constructors that fully copy the entire data structure:
Node* Copy(Node* root)
{
return new Node(*root);
}