How can I assign the "this" pointer as "temp"? - c++

I call a function interleave that looks like
void AddressLinkedList::interleave(AddressLinkedList& other) {
AddressLinkedList temp;
AddressListNode* thisCur = this->head;
AddressListNode* otherCur = other.head;
for (int i = 0; i < this->length + other.length; i++) {
if (i % 2 == 0) {
temp.insertEnd(thisCur->data);
thisCur = thisCur->next;
}
else if (i % 2 != 0) {
temp.insertEnd(otherCur->data);
otherCur = otherCur->next;
}
}
return;
}
This function is supposed to interweave a singly linked list A with a singly linked list B along the lines of if A looked like "1, 2, 3" and B looked like "4, 5, 6", then the call linkedListA.interleave(linkedListB) should make A "1, 4, 2, 5, 3, 6". I've successfully managed to create a list like this, the problem is it that it's the temp list, but I don't know how to make it so it would be the this pointer with an end goal linkedListA be the aforementioned "singly linked list A". In case it matters, below is the overloaded assignment operator and the insertEnd function.
void AddressLinkedList::insertEnd(const Address& value) {
if (length == 0) {
this->insertStart(value);
return;
}
AddressListNode* temp = new AddressListNode(value);
length++;
tail->next = temp;
tail = temp;
}
AddressLinkedList& AddressLinkedList::operator=(const AddressLinkedList& other) {
delete this;
AddressListNode* current;
current = other.head;
while (current != nullptr) {
insertEnd(current->data);
current = current->next;
}
return *this;
}

Since interleave is defined as a member function of AddressLinkedList it should modify (and work on) the object it was called on. So you don't need to (and you shouldn't) create a temporary list to use it to build your resulting collection and then "assign" it as this. It is possible with some new, delete and raw pointer trickery, but I wouldn't recommend this (the idea would be to create AddressListNode* as head and then assign that new head where the original one was, but you would also had to delete previous chain of AddressListNode* from original head to avoid memory leaks, as I said, not recommended).
Assuming that your code that calls this method looks like this:
AddressLinkedList A;
AddressLinkedList B;
... //inserting values to A and B
A.interleave(B);
Your interleave implementation should looks more like this (it's more of a proof on concept, than working solution, I didn't compiled it):
void AddressLinkedList::interleave(AddressLinkedList& other) {
AddressListNode* thisCur = head;
AddressListNode* otherCur = other.head;
while (thisCur != nullptr) { //assumig that last node points to nullptr
AddressListNode* nextNode = thisCur->next;
AddressListNode* otherNext = otherCur->next;
thisCur->next = otherCur; //attach it to node from other
thisCur = thisCur->next; //advance to next node
thisCur = nextNode; //reattach node that was originally after current
thisCur = thisCur->next; //advance again to next node
otherCur = otherNext ; //advance on other
}
other->head = nullptr; //loop above hijack nodes from other
}
All this code do is, it takes heads of both of your collection, iterate over this and for every node it attaches corresponding node from other. Effectively it will modify your object on which you originally called interleave method. However due to modifying AddressListNode pointer it will also destroy your original AddressLinkedList you passed as and argument to interleave. So you should probably modify it in a way that for thisCur->next = otherCur; actually create a copy of an Address and create new node.

Related

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.

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.

Deleting Root Node of a Binary Search Tree

I have this function for deleting a node in a binary search tree which seems to be working EXCEPT in the case where I ask it to delete the root node. It is supposed to take the right-most value on the left and replace the node with that; however, once that happens, the new root node's children pointers don't seem to point to the original root node's children. Code is as follows:
bool delete_node(Node*& root, TYPE data) {
Node* toDelete;
Node* parent;
// This function is defined appropriately elsewhere, and finds the target to be deleted
toDelete = find(data, root);
if (!toDelete) {
return false;
}
// This function is defined appropriately elsewhere, and finds the parent of the node to be deleted
parent = find_parent(root, toDelete);
// Other cases left out because they work
// If the target node has two children:
if (toDelete->left && toDelete->right)
{
// find rightmost child on left that is a leaf
Node *replacement = toDelete->left;
while (replacement->right)
{
replacement = replacement->right;
}
// set the target node's data
toDelete->data = replacement->data;
if (parent)
{
if ( parent->data < toDelete->data )
{
parent->right = replacement;
} else
{
parent->left = replacement;
}
} else
{
// if node has no parents, then it is the root and should be replaced with replacement
// This line here is what seems to be causing my trouble...I think
root = replacement;
}
parent = find_parent(toDelete, replacement);
if (parent)
{
if (parent->left == replacement)
parent->left = NULL;
else
parent->right = NULL;
}
delete toDelete;
return true;
}
}
Thanks in advance!
what I ended coming up with was this: keep track of the parent node that is one above the node that replaces the node to be deleted. there will then be 2 cases to consider: the parent is the node to be deleted and parent is not the node to be deleted. by replacing the appropriate parts of the tree at the right case, the structure and invariants of the tree remained ok and the node to be deleted was successfully deleted. technically, it would be the data at the node to be deleted.
else if (toDelete->left != NULL && toDelete->right != NULL) {
// find rightmost child on left that is a leaf
Node* replacement = toDelete->left;
parent = toDelete;
// parent is now the parent of the replacement
while ( replacement->right ) {
parent = replacement;
replacement = replacement->right;
} // By the end, parent will be the node one above replacement
toDelete->key = replacement->key;
if (parent == target)
parent->left = replacement->left;
else
parent->right = replacement->left;
delete replacement;
return true;
}
This is what I did to make it work. Just check if the node is the root node, and if so, set the new root. Below is the working code I have. The three places marked by asterisks is what I added to make it work. All the other lines of code is just standard textbook theory.
inline NamesBinaryTree::Node* NamesBinaryTree::Node::removeNode (Node*& node, const Female* female, stringComparisonFunction s) { // Taken from p.253 of Alex Allain's "Jumping Into C++".
if (!node)
return nullptr;
if (node->femaleInfo.first == female->getName()) {
if (!node->left) { // i.e. node has either one child or zero children.
Node* rightNode = node->right;
if (node->isRoot()) // ***
namesBinaryTree.setRoot(rightNode); // Tested to work correctly. Note that we cannot call 'delete node;', since that will delete the very root that we are setting!
else
delete node;
return rightNode; // This will return nullptr if node->right is also nullptr, which is what we would want to do anyway since that would mean that node has zero children.
}
if (!node->right) { // i.e. node has exactly one child, namely its left child, in which case return that left child.
Node* leftNode = node->left;
if (node->isRoot()) // ***
namesBinaryTree.setRoot(leftNode);
else
delete node;
return leftNode; // This will never be nullptr, else the previous if condition would have been met instead.
}
Node* maxNode = findMaxNode(node->left); // node has two children, so it shall be replaced by the largest valued node in its left subtree.
maxNode->left = removeMaxNode(node->left, maxNode); // Note that maxNode->left = node->left is not enough because without actually removing maxNode, the node that was pointing to maxNode will now be pointing to maxNode in its new position (and the subtree under it), and the subtree that was under maxNode will now be gone.
maxNode->right = node->right;
if (node->isRoot()) // ***
namesBinaryTree.setRoot(maxNode); // Tested to work correctly.
else
delete node;
return maxNode;
}
else {
const int result = (*s)(female->getName(), node->femaleInfo.first);
if (result < 0)
node->left = removeNode(node->left, female, s); // This assignment can only work if node is passed by reference (hence the parameter Node*& node), at least this is what "C++ Essentials" did in their solution, p.247.
else // Don't use 'else if (result > 0)'. Let the equality case be covered here too (just as in NamesBinaryTree::Node::insertNode).
node->right = removeNode(node->right, female, s); // Again, this assignment can only work if node is passed by reference (hence the parameter Node*& node).
}
return node; // So if node->femaleInfo.first != female->getName(), then the same node is returned, which means that the two assignment lines above don't change any values.
}

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.

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