Problems replacing head of a linked list - c++

Writing a function to do a head insert on a linked-list. It's half working as in it's inserting the object into head and reattaching the list but I'm losing my original head node in the list somehow.
If list is [green, red, blue] and I try to insert yellow, it will work but the new list will be [yellow, red, blue].
Node class is:
template<class T>
class Node
{
public:
Node(T theData, Node<T>* theLink) : data(theData), link(theLink){}
Node<T>* getLink( ) const { return link; }
const T& getData( ) const { return data; }
void setData(const T& theData) { data = theData; }
void setLink(Node<T>* pointer) { link = pointer; }
private:
T data;
Node<T> *link;
};
List is stored into a queue, so the head insert is a method of that class. Queue has private variables front and back that point to the corresponding positions of the list.
template<class T>
void Queue<T>::headInsert(T& theData)
{
Node<T> *temp;
temp = front->getLink();
front->setLink(new Node<T>(theData, temp->getLink() ));
front = front->getLink();
}

Your problem is in your setLink call:
template<class T>
void Queue<T>::headInsert(T& theData)
{
Node<T> *temp;
temp = front->getLink();
front->setLink(new Node<T>(theData, temp->getLink() )); // Right here
front = front->getLink();
}
You actually have a number of problems. First off, let's suppose we have the following test list:
front = Red -> Green -> Blue -> NULL
The call temp = front->getLink() yields the following output:
temp = Green -> Blue -> NULL.
The new Node<T>(theData, temp->getLink()) call, where theData = Yellow, then yields:
new Node<T>(theData, temp->getLink()) = Yellow -> Blue -> NULL.
Calling front->setLink(new(...) then gives you:
front = Red -> Yellow -> Blue -> NULL
Lastly, front = front->getLink():
front = Yellow -> Blue -> NULL.
This is not what you want. You simply want to take yellow and pop it on the front of the list:
template<class T>
void Queue<T>::headInsert(T& theData)
{
front = new Node<T>(theData, front);
}
No need to modify internal pointers. Just point front to be the new node containing your data, with it's next pointer pointing to the old data.

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.

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

How to pass pointers correctly for custom class

The backPtr_ of last node is pointing to itself at the time of generating trajectory.
This is mostly happening due to the backptr__ is pointing at the back of openNodes and while exploring a node it is last element due to pop_heap.
Any work around for this?
I have already tried to keep the openNodes as vector of Node objects rather than of pointers.
init_node.calculateF();
vector<Node*> openNodes;
openNodes.push_back(&init_node);
vector<vector<coord_t>> traj;
while(!openNodes.empty()){
pop_heap(openNodes.begin(), openNodes.end(), NodePtrCompareGtr());
Node* newNodePtr = openNodes.back();
Node newNode = *newNodePtr;
openNodes.pop_back();
traj = newNode.exploreNodes(openNodes, openSet, closedNodes, &newNode);
}
class Node
{
Node *backPtr_ = NULL;
public:
void setBackPtr(Node* nodeptr){
backPtr_ = nodeptr;
}
vector<vector<coord_t>> exploreNodes(vector<Node*> &openNodes){
newCoordList = generateCoords();
vector<Node*> newNodeList;
if(goal_reached(this)){
return generate_traj(this);
}
for(auto const& newCoords : newCoordsList){
Node *newNode = new Node(...);
newNodeList.push_back(newNode);
}
for(auto & i : newNodeList){
...
i->setBackPtr(this);
openNodes.push_back(i);
make_heap(openNodes.begin(), openNodes.end(), NodePtrCompareGtr());
...
}
}
I want to store the backPtr_ correctly to store the correct previous node.

Re-balancing a red-black tree after inserting not working. (C++)

I'm working on my C++ university assignment, and I have a problem with re-balancing a red-black tree after inserting a node in it. Everything works when inserting a root node, but once I insert more than the root node, the program crashes. This bug is driving me crazy and it's probably some silly mistake as I'm VERY new to C++.
It also works perfectly if I comment out the 2nd, 4th and 5th if statements in the putHelper function. I'm thinking the problem is maybe because I'm dereferencing uninitialised pointers in those if statements, but I'm not really sure, and if that is the case, how would I go about fixing it?
I'm posting relevant code snippets below, but if anyone wants to try running the code, I can post that too. It's very much a work in progress which hasn't been tested much yet (and I still need to code a remove function).
This is the header file, data.h:
http://pastebin.com/Fr1SKERV
And this is the main tester file, main.cpp:
http://pastebin.com/UxKRaG53
Here are relevant code snippets:
Node class declaration (K and V are generic variables):
class Node
{
public:
K key; // The index of the node.
V value; // The value of the node.
Node *right; // A pointer to the right subtree.
Node *left; // A pointer to the left subtree.
bool isRed; // TRUE if the node is red and FALSE if the node is black.
Node(K key, V value) // Constructor.
{
this->key = key;
this->value = value;
this->right = 0;
this->left = 0;
this->isRed = true;
}
};
Main insert function:
template<typename K, typename V> void Map<K, V>::put(K key, V value) // Function to insert a new node to the tree.
{
root = putHelper(root, key, value);
root->isRed = false;
size++;
}
Insert helper function:
template<typename K, typename V> typename Map<K, V>::Node *Map<K, V>::putHelper(Node *x, K key, V value) // Recursive helper function for put that traverses the tree and inserts a new node at the proper position, after which it balances the tree.
{
if (x == 0)
{
return new Node(key, value); // If the position for the new node was found...
}
if ((x->left->isRed) && (x->right->isRed)) // If both children nodes are red...
{
flipColour(x);
}
if (key == x->key) // If the key is already in use...
{
x->value = value; // Update the node with the new value.
}
else if (key < x->key)
{
x->left = putHelper(x->left, key, value); // Move to the left child.
}
else
{
x->right = putHelper(x->right, key, value); // Move to the right child.
}
if (x->right->isRed) // If the child node to the right of the parameter node is red...
{
x = rotateLeft(x);
}
if ((x->left->isRed) && (x->left->left->isRed)) // If the child node to the left of the parameter node and the child node to the left of that are both red...
{
x = rotateRight(x);
}
return x;
}
Red-black tree balancing functions (flip colour and rotate):
template<typename K, typename V> void Map<K, V>::flipColour(Node *x) // Function to flip the colour of a node and its two children.
{
x->isRed = !x->isRed; // Flip the colour of the parameter node.
x->left->isRed = !x->left->isRed; // Flip the colour of the left child node.
x->right->isRed = !x->right->isRed; // Flip the colour of the right child node.
}
template<typename K, typename V> typename Map<K, V>::Node *Map<K, V>::rotateLeft(Node *x) // Function to rotate a set of three nodes to the left.
{
Node *y = x->right; // Create a new node from the parameter node's right child node.
x->right = y->left;
y->left = x;
y->isRed = y->left->isRed;
y->left->isRed = true; // Set the new node's left child node to red.
return y;
}
template<typename K, typename V> typename Map<K, V>::Node *Map<K, V>::rotateRight(Node *x) // Function to rotate a set of three nodes to the right.
{
Node *y = x->left; // Create a new node from the parameter node's left child node.
x->left = y->right;
y->right = x;
y->isRed = y->right->isRed;
y->right->isRed = true; // Set the new node's right child node to red.
return y;
}
Any help would be greatly appreciated as the deadline for this assignment is approaching soon! Thanks in advance :).

Queue appending more then one entry

I keep getting the first entry appended 4 times instead of one time.. when I append my first entry to the Queue it appends it 4 times..I thought this might be the problem..but it looks like it isn't. I can't find where the problem is..
I also created a print function for the nodes, and it showes that there are 4 of the same entries in the queue, so it is not a printing problem. And it doesn't look like it's in the read function. Maybe it's in the logic of the append function?? Still working on it..
This is the output: 3X^2 + 3X^2 + 3X^2 + 3X^2 + 1 but it should be 3X^2 + 1
This is my append function:
//Append(Add) item to back of queue.
Error_code Extended_queue::append(const Queue_entry &item) {
Node<Queue_entry> *new_rear = new Node<Queue_entry>(item);
if(rear == nullptr){
front = new_rear; // I also tried rear = new_rear; front = rear; rear = new_rear;
}
else {
rear->next = new_rear;
rear = new_rear;
}
return success;
}
And here is the code that prints the output:
This is the node code declaration:
#ifndef NODE_H
#define NODE_H
enum Error_code{success,underflow,overflow}; // Used in node containing classes
template <class Node_entry> // Template to allow for more varience
// Part of a linked structure
struct __declspec(align(1)) Node{
Node_entry entry; // Data contained in the node
Node *next; //Pointer to next node
//constructors
Node(); // Creates empty node
Node(Node_entry item, Node *add_on = nullptr); // Creates node with specified data and pointer to next node
};
/* Post: The Node is initialized to contain nothing, and to have a null pointer.*/
template <class Node_entry>
Node<Node_entry>::Node()
{
entry = nullptr;
next = nullptr;
}
/* Post: The Node is initialized to contain item, and to point to add_on.*/
template <class Node_entry>
Node<Node_entry>::Node(Node_entry item, Node *add_on)
{
entry = item;
next = add_on;
}
#endif
It looks like the copy constructor had bad logic. After I fixed th constructor, the driver only returned the first term as front and rear entry. So I had to fix up the overloaded = operator as well.
New Code(for copy constructor):
Extended_queue::Extended_queue(const Extended_queue &original){
Node<Queue_entry> *temp_node, *original_node = original.front;
if(original.empty()){ //original queue is empty, set new to NULL
front = nullptr;
rear = nullptr;
}
else
{
front = temp_node = new Node<Queue_entry>(original_node->entry,nullptr);
while(original_node->next != nullptr)
{
original_node = original_node->next;
//needed to change next and still incriment
temp_node->next = new Node<Queue_entry>(original_node->entry, nullptr);
temp_node = temp_node->next;
//rear->next = temp_node;
//rear = temp_node;
}
rear = temp_node->next;
}
}