Nested Doubly Linked Lists in C++ - c++

What is the best way to go about storing doubly linked lists inside of one doubly linked list? Preferably, I would like to use only one struct, like so:
struct node{
string data;
node* next = NULL;
node* prev = NULL;
};
and use this to be able to store a doubly linked list inside of a doubly linked list to hold all of my doubly linked lists.
I have an ordinary insert function, but that wouldn't work because the parameters are (node*& start, string data). So I've created another insertion method that attempts to store a doubly linked list into a node of a larger doubly linked list, but it gets cloudy from there. Any help would be appreciated.

Your node consists of data and links.
You could insert a linked list as part of the data section:
struct Node
{
std::string Data
std::list</*...*/> nested_list;
Node * previous;
Node * next;
};
If you don't like using std::list you could go with this:
struct Nested_Node
{
Nested_Node * previous;
Nested_Node * next;
/* add data if necessary */
};
struct Node
{
std::string data;
Nested_Node * nested_head;
Nested_Node * nested_tail;
Node * previous;
Node * next;
};
The above structures depend on how you want your nested linked list organized.
Each Node contains the head and tail of a linked list. If you declare the nested list as a separate structure, you could replace the Nested_Node pointers with the list class.

Related

Deep copy queue recursively C++ (Implemented using a doubly linked list)

I'm building a queue using a doubly linked list. I want my deep copy constructor to recursively deep copy the entire queue however I get a segmentation fault when I do the following:
// Recursive helper method for deep copy constructor
void queue::copyAllNodes(Node* og, Node *cpy) {
if(og == nullptr) back = og;
else {
cpy->previous = og->previous;
cpy->data = og->data;
cpy->next = og->next;
copyAllNodes(og->next, cpy->next);
}
}
my constructor has another helper function that allows me to pass in the original and the copy node i want to copy.
First, understand you're not actually copying anything here. You're just enumerating by recursion and assigning pointers. At best that is a shallow copy; in reality your algorithm is completely broken. There are ways to copy a linked list recursively, including bidirectional linked lists. Whether it is wise to do so is another story.
Unidirectional List
Before getting into the subject of a bidirectional linked list, consider the base case of a unidirectional list. Suppose you have a linked list with nodes like this:
template<class T>
struct Node
{
T data;
Node *next;
Node(T dat, Node *nxt = nullptr)
: data(std::move(dat))
, next(nxt)
{
}
};
Now suppose you want to make a deep copy of this recursively. In its most simple form the algorithm for a recursive copy would be:
Node *copyDeep(const Node *p)
{
Node *res = nullptr;
if (p)
res = new Node(p->data, copyDeep(p->next));
return res;
}
Bidirectional List
Introducing a double-linked node (both next and prev members) makes this a bit more challenging, but not by much. First the node has to be modified to include the new member:
struct Node
{
T data;
Node *next;
Node *prev;
Node(T dat, Node *nxt = nullptr)
: data(std::move(dat))
, next(nxt)
, prev(nullptr)
{
}
};
With that, copyDeep can be modified to remember the added node to be used as an added argument to the recursed call. One way of doing that is:
Node *copyDeep(Node *p, Node *prev = nullptr)
{
if (p)
{
Node *res = new Node(p->data);
res->prev = prev
res->next = copyDeep(p->next, res);
return res;
}
return nullptr;
}
In both cases it is easier, faster, and less error prone (including stack overflows) to do this iteratively. In answer to your question, yes you can recursively copy a linked list. Whether it's a good idea to do so I leave to you.

Nested linked list in C++

I'm trying to build a nested linked list in C++ (pretty new to C++).
The node in the list could be an integer value or another linked list that has all integer values.
I have gone through other posts on SO, and I understand I should use a union for multiple data types for the node data type.
This is what I have until now.
class linkedList {
private:
struct node {
union data {
int val;
linkedList* list;
};
data currData;
node* next; // a pointer which will point to the next node
}*p;
My question is how do I start allocating the list pointer within the node struct.
For val, I know I can do p->currData->val =5, for example.
I wouldn't use a union. I would just keep a value for each and a typefield of some sort so you know what it is.
class LinkedList {
public:
class Node {
LinkedList * list = nulptr;
int value = 0;
Node * next = nullptr;
};
};
In this case, if list is nullptr, then it's not a node pointing to a new list. Or you could explicitly add a type, but for something this simple, I probably wouldn't.
p->value = 5;

Printing elements of a linked list, but instead, it prints reversed C++

here i simply wanted to print the elements of the linked list i created but it is printing the list in REVERSE order. looks like there is a mistake in the code.help me solve it
push function adds node to linked list every time we input element to be inserted in linked list.I've passed reference of head and data. A node gets dynamically created every time push fuction called. I am using c++ here.
#include<iostream>
using namespace std;
class node{
public:
int data;
node* next;
};
//creating linked list
void push(node** head_ref,int new_data) //passing address of head and data to put in list
{
node* new_node=new node(); //new node created
new_node->data=new_data; //data inserted
new_node->next=*(head_ref);
*(head_ref)=new_node;
}
int main()
{
node* head=NULL;
int n;
cin>>n; //number of elements in linked list
for(int i=0;i<n;i++)
{
int val;
cin>>val;
push(&head,val); //push function which creates a linked list
}
//while loop for printing elements of linked list
while(head!=NULL)
{
cout<<head->data;
head=head->next;
}
return 0;
}
What you currently do is assigning each node to be the predecessor of the current head, so in the end your head will be the latest element you added , its successor the second last element, its successor the third last element etc. and thus resulting to a reversed list.
You should assign the new node as successor of the current "head", like this:
void push(node** tail_ref,int new_data) //passing address of tail and data to put in list
{
node* new_node=new node(); //new node created
new_node->data=new_data; //data inserted
(*tail_ref)->next= new_node;
*(tail_ref)=new_node;
}
Note that I renamed head_ref to tail_ref in the snippet above, which better describes what the pointer actually represents: a pointer to the current last element of the list, hence the tail of the list.
Of course, you will need to save the pointer to the first element. Otherwise you won't be able to iterate through your linked list.
Extension to Simon's answer, which is correct so far:
You already have a class 'node' – why not create a class 'list' or 'linked_list' as well:
class LinkedList
{
node* m_head = nullptr;
node* m_tail = nullptr;
};
Now you always have head and tail combined and don't need to store them separately. Note that in above example, they are both private. That's actually how you should design your class. If you don't, then you allow a user to break the list implementation from outside (someone might, for instance, just set one of these pointers to nullptr, producing a memory leak in case of head).
However, now you will have to provide appropriate means to access and modify the list:
class LinkedList
{
public:
void append(int new_data); // as Simon proposed
void prepend(int new_data); // your implementation
int head();
int tail();
void dropHead();
//void dropTail(); // is an O(n) operation with singly linked list, though!
private:
node* m_head = nullptr;
node* m_tail = nullptr;
};
The node class is very closely linked to your list, you might consider not letting it be a stand-alone class, but making it a nested class instead. There's yet quite a bit to add (e. g. how to iterate over the list). To get some hints I recommend to peek a bit into STL and get familiar with the concept of iterators.
Finally: Stop re-inventing the wheel. STL already provides fully implemented doubly (std::list) and singly (std::forward_list) linked lists. It's fine to experiment with an own implementation to get to know how the winds blow, but once you know, switch back to STL.

How to merge two Doubly Linked Lists (Accessing next link)

I am trying to merge two doubly linked lists. I created a function already that inserts a new node and in the correct order. The parameters are set by my professor so I can not change them. I am able to add the first item to List1 but am unable to add anymore.
I am getting errors while trying to continue to traverse List2 and add more items to List1. I have tried recursion and a do while loop. While trying to use a do-while loop
struct nodeType{
int info;
nodeType *next;
nodeType *back;
};
class OrderedDoublyLinkedList{
public:
//Insert x in appropriate place in the list to keep it
sorted
void insertNode(int x);
void mergeLists(OrderedDoublyLinkedList &List1,
OrderedDoublyLinkedList &List2);
private:
int count;
nodeType *first;
nodeType *last;
};
void
OrderedDoublyLinkedList::mergeLists(OrderedDoublyLinkedList
&List1, OrderedDoublyLinkedList &List2){
//First Technique
do{
List1.insertNode(List2.first->info);
List2.first->next; //Error: Expresion result unused
}
while(List2.first!=NULL)
//Second Technique
while(List2.first!=NULL)
List1.insertNode(List2.first->info);
mergeLists(&List1, &List2.first->next);
//If I try to use this it says cannot bind to a temporary of
type
I need help accessing the next node to add the rest of the info to List1.
Looks like a simple while loop is all you need
nodeType* n = List2.first;
while (n != NULL)
{
List1.insertNode(n->info);
n = n->next;
}
Although I'm still worried whether this is an acceptable solution. You said that you need to move List2 into List1, and that's not what this code does, This code copies List2 onto List1, List2 is unaffected by this code.

create a doubly linked list in C++

I'm creating a programme that needs to read data from a spreadsheet in CSV form and assigns it to a doubly linked list in C++.I have created a singly linked list but I'm at a loss as to how to use this idea to make a doubly linked list. I understand you require a previous pointer but I am unsure as to actually implementing the code.
code for my singly linked list:
to add to the list:
if (!m_head)
{
m_head = new Node(name, reference,latitude,longitude);
}
else
{
Node *current = m_head;
while (current->getNext() != 0)
{
current = current->getNext();
}
current->setNext(new Node(name, reference,latitude,longitude));
}
please note: Node is a separate class to store data about the node e.g. name.
Each List Node must a have a pointer to the previous and to the next List Node.
The List is then the container of List Nodes , linked together as a chain.
struct ListNode;
typedef struct ListNode {
struct ListNode *next;
struct ListNode *prev;
void *value;
} ListNode;
typedef struct List {
int count;
ListNode *first;
ListNode *last;
} List;
You need then to implement the methods push and pop accordingly.
The tricky part is the remove method. Store the two pointers of the previous and next Node that you want to delete, and then assign them accordingly to the previous and following node:
ListNode *after = node->next;
ListNode *before = node->prev;
after->prev = before;
before->next = after;
This article may help you, full code and explanation
http://c.learncodethehardway.org/book/ex32.html