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.
Related
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.
For example, my instructor said something about not having any memory freed, and deleting pointers when doing operations with linked lists. Furthermore, he said that while doing operations on a doubly-linked lists, you should make sure that your edge cases are okay. Can anyone expand on this? I'm not sure I get what he fully means.
For example, this is the sort of linked list we are working on:
struct Node {
Node *next;
Node *prev;
T datum;
};
Node *first; // points to first Node in list, or 0 if list is empty
Node *last; // points to last Node in list, or 0 if list is empty
When dealing with pointers, you always want to make sure you delete any new objects that are no longer in use. That's so there aren't any memory leaks.
Edge conditions are, for example, when inserting an element, does it work for an empty list, when the item will be inserted as the first element, as the last element? Normally, when implementing insert we do the logic for a typical element (i.e. one in the middle of an existing list). But it should work for all cases. The cases I mentioned could be considered edge conditions and have to be considered for each an every operation you want to implement for the list.
Some of the edge cases might be
(a) No node
(b) Only one node
(c) Adding node at head/tail
(d) Avoiding infinite loop while traversing list
(e) Avoiding memory leaks and dangling pointers
These are the basic checks that ought to be made.
Since you are using a ´struct´, instead of a ´class´, implement some functions for operations for each node.
UPDATE:
I mention class because, the functions I comment, are usually implemented as object' methods, in the object-oriented version of a linked-list,
yet these operations apply as well in procedural programming.
Example:
struct Node {
Node *next;
Node *prev;
T datum;
};
Node *first; // points to first Node in list, or 0 if list is empty
Node *last; // points to last Node in list, or 0 if list is empty
void NodesLink(Node* A, Node* B)
{
if ((A != NULL) && (B != NULL))
{
A->next = B;
B->prev = A;
}
} // void NodesLink (...)
void NodesInsertAfter(Node* A, Node* NewNode)
{
if ((A != NULL) && (NewNode != NULL))
{
Node* B = A->next;
NodesLink(A, NewNode);
NodesLink(NewNode, B);
}
} // void NodesLink (...)
That independent utility functions will make your code more consistent, and easy to debug and fix.
I'm currently taking data structures and algorithms class and turns out it is heavily geared on the concepts of linked lists. These are some things I have difficulty understanding:
How do I insert a number into data?
How do I move from one node to the next?
How do I call the Node class in main and print out the data values?
I have the following code. Am I doing it wrong?
#include <iostream>
using namespace std;
class LinkedList
{
class Node
{
public:
Node (int data, Node *n);
int data;
Node *next;
};
Node *head;
};
int main()
{
LinkedList::Node NodeObj;
NodeObj.data = 5;
cout <<NodeObj.data;
return 0;
}
A nice tutorial is at: http://www.zentut.com/c-tutorial/c-linked-list/
From a programming perspective, normally your LinkedList class would have some methods to do the things you asked about, for example:
Add - create a new entry at the end of the linked list
InsertAfter(Node *n) - create a new entry after indicated node in the listed list
Remove(Node *n) - removes the indicated node from the linked list
Count() - returns a count of the number of nodes within the linked list
Get(long i) - returns a pointer to the ith entry in the linked list
Find(some type of criteria) - return a pointer to the node that matches
Destroy - remove all the nodes in the linked list
Then your mainline just invokes these methods to utilize the linked list (the whole point of object encapsulation). Note that there is a LinkedList object instantiated, and it instantiates and manages the Node objects.
So if you had 10 numbers to store from some input array (inArray), you could do something like:
Node* n;
llObj = new LinkedList;
For (i=0; i<=9; i++) {
n = llObj.add();
n.data = inArray[i];
}
To step through the linked list, you would do something like:
For (i=0; i<=llObj.Count(); i++) {
n = llObj.get(i);
n.data = n.data + 1;
}
However, if you write yourself a .get() method from the code samples below, you will see that above code is terribly inefficient, and is not the ideal way to step through the entire linked list from mainline code.
To find the number 6:
n = llObj.find(6);
And so forth. Normally a linked list does not store just one data value such as in your example, but rather stores a structure or an object. Hence methods like Find become more useful because you can create Find methods that look at various fields in a structure or an object.
An Add method just traverses all the existing entries in the listed list until the last one is found, then creates a new entry, and links the former last entry to the now new last entry.
Node* LinkedList::add() {
void *n = NULL;
if (head != NULL) {
// one or more Nodes do exist
// first loop until we find the last-most node who's n.next == NULL
n = head;
while (n.next != NULL) n = n.next;
// found the last node, now allocate a new Node, and store a pointer to it in the formerly last node's .next property
n.next = new Node;
n = n.next;
// IMPORTANT: ensure this new last Node's .next is forced to be null
n.next = NULL;
}
else
{
// the header is NULL, so there is no first node yet
// allocate a new Node and store a pointer to it in the LinkedList header
head = new Node;
n = head;
// IMPORTANT: ensure this first Node's .next is forced to be null
n.next = NULL;
{
return n;
}
Note the While loop ... this is the key linked-list traversal mechanism. That loop checks the current node's .next field ... if it has a non-NULL pointer, then the loop cycles by copying that .next pointer to the loop pointer n, and tests again. Once the loop finds a node who's .next is NULL, then the lastmost node has been found, and the loop exits, with n containing the pointer to that lastmost node.
Note also the If statement concerning the .head property of the LinkedList class. One always has to do some special code for accounting for when the linked list is empty. There are a couple of ways of handling that; I chose the one that uses the least data memory.
Removing a node means just "skipping over it" in the linked list. We traverse the listed list until we find the one to remove, the we just "move back" its .next property to the prior entry's .next pointer. A good image is in the Linked List wikipedia entry:
A code example:
void LinkedList::remove(Node* nodeToRemove) {
// do nothing if we've been given a NULL pointer
if (nodeToRemove == NULL) return;
Node *n;
if (nodeToRemove == head) {
// the node to remove is the very first node, so set the head
// to the contents of the first node's .next property
head = n.next;
delete n;
return;
}
// need to find the indicated node; the following loop locates the
// node that is immediately before the node to be removed; note too
// that we have to test for the end of the linked list because the
// caller may have provided a bad pointer value
n = head;
while (n.next != NULL && n.next != nodeToRemove) n = n.next;
if (n.next == NULL) return; // reached end of linked list without finding the node
// good, the node immediately before the node to remove has been found!
Node* r = n.next; // this is inefficient code but want to make it very clear to newbies
n.next = r.next;
delete r;
}
Note that again we have to do some special logic concerning the LinkedList header. And do pardon the fact that I've used returns in the code; many finicky stickers would consider that a no-no. Also note in the code above, we don't need to do special logic to account for the end of the linked list, only just its beginning. If the node-to-remove is the last node in the linked list (and its r.next therefore == NULL), then the "n.next = r.next" line of code just moves the NULL back one position in the linked list, which is exactly what we would want.
You should be able to now figure out how to create all those other methods in your LinkedList class that I mentioned.
===============================
I do like someone's answer that unfortunately he deleted. For a 5 year old, a linked list is indeed a lot like the game of Treasure Hunt. In a Treasure Hint, you have to physically go to each location to get the clue to the next location. And in a linked list you have to access the location of a node to find the address of the location of the next node. A perfect analogy, and kudos for the answerer that first provided it.
I am done with insertion, search in circular linked list but for removal I am getting compiler errors...
Following is my structure for nodes.
struct node
{
int p_data;
struct node* p_next;
node(node* head, int data)
{
p_next = head;
p_data = data;
}
explicit node(int data)
{
p_next = nullptr;
p_data = data;
}
};
node* remove_circular(node* head, node* target)
{
if (head == target->p_next)
{
delete head;
return nullptr;
}
auto next_pointer = target->p_next;
target->p_data = next_pointer->p_data;
target->p_next = next_pointer->p_next;
delete target->p_next;
return target;
}
and in main function I call
head = remove_circular(head, head);
head = remove_circular(head, temp);
this is to remove head element and another element that temp points to.
But I am getting errors
Anybody has any idea to remove one element from circular list??
I changed it to delete target->p_next;
but now it deletes everything in the list.
Any idea???
This is how a circular linked list works:
Each node points to the next in line, and the tail of the list points to the header node. That's the difference from a circular linked list to a regular linked list (which, in the case above, would make 37 point to a terminator null).
In the case of your list having only one object, then it should look something like this:
So, as you can see, there is no object pointing to null anywhere, yet it happens on your code with your explicit constructor (which will run if I write node n = node(12)).
I suggest you take a look at this link to have a better understanding of how your algorithm should look like.
Once you resolve your compiler error, you are still going to have algorithmic issues. I suggest you draw a circular list on paper and think about the steps required to remove an element. Consider all the cases, for example: empty list, list of 1 item, element not in the list, etc.
You need to consider several things.
1.) the case of an empty list
if(head == nullptr){//Empty list case
return nullptr;
}
2.) The target to be removed is the head node and this is the only node in the list.
if (head == target && target->p_next == head){
create a temp node with the data value of target
target = nullptr;//Since nothing points to target now it is for all intents and purposes deleted from the list but the data is still there so you can do something with it. I assume this is necessary because you return a node *.
return the temp node
}
3.) Create a loop that iterates through the entire list. You have something that would only delete the next node which works if you have a two item list and target was the second item.
auto next_pointer = head->p_next;//could not be target->p_next as this assumed
while (next_pointer->p_next != target){//This while loop traverses the list rather than just deleting the next entry.
4.)Inside you loop add a check to see if the list has been traversed and target was never found.
if (next_pointer->p_next == head){
return nullptr;
}//end IF
5.) Inside the loop add the else case which means target was in an arbitrary location in the list. Since I gave you the rest I'll leave you to get this part. It's not hard just a few lines longer than the statements above.
Which of these is a more correct way to store the first object in a linked list?
Or could someone please point out the advantages/disadvantages of each. Thanks.
class Node
{
int var;
Node *next;
static Node *first;
Node()
{
if (first == NULL)
{
first = this;
next = NULL;
}
else
//next code here
}
}
}
Node* Node::first = NULL;
new Node();
-- OR --
class Node
{
int var;
Node *next;
Node()
{
//next code here
}
}
Node* first = new Node();
The latter is definitely preferable. By making the first node pointer a static class member, you are basically saying that there will only be a single linked list in your whole program.
The second example lets you create several lists.
The first example has the definite drawback of only being able to create a single linked list in your entire program, so I wouldn't do that.
The second works fine, but doesn't shield the user of the class from how the linked list works. It would be better to add a second class, for example named LinkedList, that stores the 'first' pointer and performs list management.
Even better, you could use std::list instead.
It's most usual to have a separate List class and a separate Node class. Node is usually very simple. List holds a pointer to the first Node and implements the various list operations (add, remove, find and so on).
Something like the following
class List
{
public:
List()
{
first = new Node();
}
void insert(int val);
void remove(int val);
// ... and so on
~List()
{
// ... clean up
}
private:
struct Node
{
int val;
Node* next;
Node(int val_ = 0, Node* next_ = 0)
: val(val_), next(next_)
{}
};
Node* first;
};
Note that you can place Node outside List if you want to, but this usually doesn't make much sense.
Presumably you may have more than one list? In which case, the static option is a non-starter.
You definitely don't want the "first" to be a static. This implies there's only one linked list in your entire program. static means that every Node in every linked list in your entire program has the same beginning.
That being said you want your Node to have the fewest responsibilities-- It make sense for it to store its value and be able to get to the next Node. It adds complexity to add the job of1 maintaining the "first" pointer. For example what happens when you insert a new element at the beginning? Then you'd have to update everyone's "first" pointer. Given the two choices above I'd chose the second choice.
I would furthermore add a third choice. Add a "linked list" wrapper that gave you easy access to "first", "last" and allow you to easily insert into and iterate through the list. Something like:
class LinkedList
{
Node* First;
Node* Last;
public:
Node* GetFirst() {return First;}
Node* GetLast() {return Last;}
// insert after "where"
void Insert(Node* where, Node* newNode);
...
}
Not uselessly limiting your code to a single list instance is one very good argument for code variant 2.
However, just from superficially looking at the two examples, the sheer number of lines of code also gives a good indication that variant 2 has merits over variant 1 by being significantly shorter.