Sorting linked list while inserting a node - c++

I am trying to create sorted linked list = sorting it while creating it. Idea is simple , insert a node - and check if previous is smaller , if so check previous of previous and so on until it finds its spot. I have created this piece of code.
struct Node{
Node *prev;
Node *next;
int value;
};
struct List{
Node *head = nullptr;
Node *tail = nullptr;
};
Here i created a node , and a "holder" for the list = reference to first and last item of the list.
void insertNode(Node *&head,Node *&tail, int value ){
Node *tmp = new Node;
tmp -> prev = nullptr;
tmp -> next = nullptr;
tmp -> value = value;
head = tmp;
tail = tmp;
}
this function checks if list is empty , if yes , it inserts node to head and tail ( e.g head = tail = there is only one node in list );
What troubles me is function to insert a node
void insertIt(Node *&head , Node *&tail , int value){
if( head == nullptr){
insertNode(head,tail,value);
}
else{
Node *tmp = new Node;
tmp -> value = value;
if( value < tail -> value){
while(value < tail -> prev -> value){
tail = tail -> prev;
if( tail -> prev == nullptr){
tmp -> next = head;
tmp -> prev = nullptr;
head -> prev = tmp;
head = tmp;
return;
}
}
tail -> prev -> next = tmp;
tmp -> prev = tail -> prev;
tmp -> next = tail;
tail -> prev = tmp;
}else{
tmp -> next = nullptr;
tmp ->prev = tail;
tail -> next = tmp;
tail = tmp;
}
}
}
If list is empty , it invokes insertNode() , if value of the node is smaller than value of previous node , it crawls the list to find its spot.
This piece code works only if the first node inserted is also a smallest node there will be. e.g
insertIt(list.head , list.tail , -1);
insertIt(list.head , list.tail , 0);
insertIt(list.head , list.tail , 7);
insertIt(list.head , list.tail , 1);
insertIt(list.head , list.tail , 2);
insertIt(list head , list.tail , 2);
works and if i print the list it is nice sorted. but
insertIt(list.head , list.tail , -2);
insertIt(list.head , list.tail , -1);
insertIt(list.head , list.tail , 7);
insertIt(list.head , list.tail , 1);
insertIt(list.head , list.tail , 2);
insertIt(list.head , list.tail , 2);
the first node isnt the smallest node , it crashes the program. I thought it was i was comparing a value to nullptr so i added the piece of code which you can see in insertIt() function and that is
if( tail -> prev == nullptr){
tmp -> next = head;
tmp -> prev = nullptr;
head -> prev = tmp;
head = tmp;
return;
}
This checks if the node is a head , and swap head with new node , making new node new head.
Why does it crashes code? I failed to find a reasonable answer to this. Also , how could I improve my "algorithm" to make it more effective?

When iterating over the list to find the position to insert a new node, you do:
tail = tail -> prev;
But the tail variable is passed by a reference, that is you modify the tail member of yout List object, thus destroying its consistency.
Use another temporary variable, named, say current or position to walk along the list, and don't modify tail unless you're appending a new node at the end of the list.
EDIT example approach
struct Node {
Node(int val);
Node *prev;
Node *next;
int value;
};
struct List{
List() : head(nullptr), tail(nullptr) {}
void insert(int value);
Node *head;
Node *tail;
};
Node::Node(int val) :
value(val), next(nullptr), prev(nullptr)
{
}
void List::insert(int value) {
Node *tmp = new Node(value);
if(head == nullptr) {
head = tmp;
tail = tmp;
return;
}
Node *pos; // find the node greater or equal to 'value'
for(pos = head; pos && pos->value < value; pos = pos->next)
;
if(pos) { // appropriate pos found - insert before
tmp->next = pos;
tmp->prev = pos->prev;
tmp->next->prev = tmp;
if(tmp->prev) // there is some predecessor
tmp->prev->next = tmp;
else
head = tmp; // making a new first node
} else { // pos not found - append at the end
tmp->next = nullptr;
tmp->prev = tail;
tail->next = tmp;
tail = tmp;
}
}

You want to do two things: find position in list where new node belongs AND insert new node at a position. So, write two functions, one to do each task. Then you can test and debug them separately before integrating. This will be much more straight forward. Further reccomendation: write unit tests for each function, before implementing the functions.
/** Find node with largest value less than given
Assumes sorted list exist. If empty, throws exception
*/
Node & FindLessThan( int value );
/** Inset new node after given with value */
InsertAfter( Node& n, int value );
It will also be handy to have a function to insert the first node, if the list is empty,
/** Insert first node with value
#return true if list empty */
bool InsertFirstNode( int value );
The point is that you should hide all the pointer twiddling in functions that can be tested, so you can write a comprehensible mainline that will work first time:
if( ! InsertFirstNode( value ) )
InsertAfter( FindLessThan( value ), value );
Since you are using C++, make your list a class and the functions members.
Implementation details: You have to worry about special cases: new value goes before head or after tail. So I suggest using an enumeration to handle these.
/** Special cases for placing a new node */
enum class eFind
{
list_empty, // the list was empty
before_first, // the new node goes before the first node in list
before_node, // the new node goes before the specified node
after_last, // the new node goes after the last node in the list
};
/** Find node with smallest value greater than given
#param[out] place eFind enumeration, one of list_empty,before_first,before_node,after_last
#param[in] value being inserted
#return n node before which value should be placed
Assumes sorted list exist.
*/
Node * FindSmallestGreaterThan( eFind & place, int value )
It also turns out to be slightly easier ( less code ) to do an InsertBefore rather than InsertAfter. You can see the code running at cpp.sh/4xitp or the github gist

1. You can't initialize members inside a structure :
struct List
{
Node *head;
Node *tail;
};
2.(a) Prototypes of functions insertIt and insertNode are wrong.You are passing head and tail using pass by reference.It should be as follows :
void insertIt(Node * head ,Node * tail ,int value)
void insertNode(Node * head,Node * tail,int value)
2.(b) When you create a node in else part you should set the next and prev pointers of your new node to NULL :
tmp->prev=NULL;
tmp->next=NULL;
2.(c) As you have passed tail using pass by reference whatever changes you make inside while loop on tail are reflected in program.Hence use temporary pointer of type Node.
3. Also the design you are using is not good.Hence I would advice you to change it.This is my implementation of linked list :
main()
{
struct List Q;
Initialize_list(&Q);
Insert_it(&Q,12);
}
void Initialize_list(struct List *L)
{
L->head=NULL;
L->tail=NULL;
}

The problem is the check value < tail->prev->value in the while loop head. This does not check that tail->prev != nullptr is true. This is a problem for the case that head == tail and value < head->value. If head != tail, your code would indeed work, because the first time value < tail->prev->value is evaluated, tail->prev != nullptr is true and the case head->next == tail would be caught by the code in the loop body.
The correct check would be tail->prev != nullptr && value < tail->prev->value. This first checks that tail->prev can be derefenced.
Then you may end with tail->prev == nullptr after finishing the while loop (due to the new condition). The check for that can be moved out of the loop, leading to the following code:
while (tail->prev != nullptr && value < tail->prev->value) {
tail = tail->prev;
}
if (tail->prev == nullptr) {
// Prepend node to the list
return;
}
// Insert node in front of tail
EDIT: You can still check the condition tail->prev == nullptr within the loop; the check after the loop would then only be useful to catch the case head == tail && value < head->value. Not doing the check in the loop has the benefit of a shorter and (in my opinion) mode readable code.

This might be the code you're looking for ;-) You can run it as-is in VS2013. It simplifies your insert function to just a few if-statements. And that can be further simplified with use of terminal elements for head & tail.
I hope this helps :-)
struct Node
{
int value; Node *prev, *next;
};
struct DoublyLinkedSortedList
{
Node *head = nullptr, *tail = nullptr;
void insert(int value)
{
// Find first node bigger then the new element, or get to the end of the list
Node* node = head;
while (node && node->value <= value) { node = node->next; }
// Once found, insert your new element before the currently pointed node, or at the end of the list
node = new Node{ value, node?node->prev:tail, node };
if (node->prev) node->prev->next = node; else head = node;
if (node->next) node->next->prev = node; else tail = node;
}
};
#include <climits>
#include <iostream>
using namespace std;
int main()
{
cout << "This is a DoublyLinkedList test." << endl << endl;
// test the list
DoublyLinkedSortedList list;
list.insert(234);
list.insert(INT_MIN);
list.insert(17);
list.insert(1);
list.insert(INT_MAX);
list.insert(-34);
list.insert(3);
list.insert(INT_MAX);
list.insert(INT_MIN);
list.insert(9);
list.insert(7);
// print nodes in order;
cout << "This are the contents of the linked list front to back" << endl << endl;
for (Node* curr = list.head; curr != nullptr; curr = curr->next) { cout << curr->value << "; "; }
cout << endl << endl << "This are the contents of the linked list back to front" << endl << endl;
for (Node* curr = list.tail; curr != nullptr; curr = curr->prev) { cout << curr->value << "; "; }
cout << endl << endl;
system("pause");
}

Related

Reversing a Link List using Iterative Approach

What is wrong with my code for reversing a linked list?
void rev(node* &head)
{
int flag=0;
node* head1=NULL;
while(head->next!=NULL)
{
node* temp1=head;
node* temp2=head;
while(temp1->next!=NULL)
{
temp2=temp1;
temp1=temp1->next;
}
if(flag==0)
{
head1=temp1;
flag++;
}
temp1->next=temp2;
temp2->next=NULL;
}
head=head1;
delete head1;
}
I was trying to solve a standard problem of reversing a link list. So i tried implementing this approach, however it seems to be going into infite loop, I am unable to understad why.
Your function is invalid.
For example the passed pointer head can be equal to nullptr. In this case this while loop
while(head->next!=NULL)
already can invoke undefined behavior.
Or there is nothing to delete in the list but the function has these statements
head=head1;
delete head1;
that do not make sense.
Even if to remove the statement with the call of delete nevertheless this does not make the function correct. For example if the list contains only one node then this while loop
while(head->next!=NULL)
will not be executed. As a result the pointer head will be set to NULL due to this statement after the loop
head=head1;
because before the loop the pointer head1 is set to NULL
node* head1=NULL;
Also it seems in this nested while loop
while(temp1->next!=NULL)
{
temp2=temp1;
temp1=temp1->next;
}
you are trying to find the last node in the list that at least is inefficient.
And your function is unclear and too complicated.
To write the function it is enough to learn the standard C++ function std::exchange declared in header <functional> that will make the code of the function more simpler and clear.
Here is a demonstration program that shows how the function that reverses a singly-linked list can be implemented.
#include <iostream>
#include <functional>
#include <iterator>
struct node
{
int data;
node *next;
};
void clear( node * &head )
{
while ( head ) delete std::exchange( head, head->next );
}
void assign( node * &head, const int a[], size_t n )
{
clear( head );
for (node **current = &head; n--; current = &( *current )->next)
{
*current = new node{ *a++, nullptr };
}
}
std::ostream & display( const node *const &head, std::ostream &os = std::cout )
{
for (const node *current = head; current != nullptr; current = current->next)
{
os << current->data << " -> ";
}
return os << "null";
}
void reverse( node * &head )
{
for ( node *current = head, *previous = nullptr; current != nullptr; previous = head )
{
head = std::exchange( current, current->next );
head->next = previous;
}
}
int main()
{
node *head = nullptr;
const int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
assign( head, a, std::size( a ) );
display( head ) << '\n';
reverse( head );
display( head ) << '\n';
clear( head );
}
The program output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> null
As you can see the function has only one for loop the compound statement of which contains only two statements
void reverse( node * &head )
{
for ( node *current = head, *previous = nullptr; current != nullptr; previous = head )
{
head = std::exchange( current, current->next );
head->next = previous;
}
}
Without using the standard function std::exchange the function that reverses a list will have one more statement as for example
void reverse( node * &head )
{
for ( node *current = head, *previous = nullptr; current != nullptr; previous = head )
{
head = current;
current = current->next;
head->next = previous;
}
}
First, a mini code review:
//
// Bigger issues implied by this function are that it is not a very good
// linked list, likely an extremely basic C-style list. However, that is
// beyond the scope of this question.
//
void rev(node* &head)
{
int flag=0; // Unnecessary
node* head1=NULL; // Prefer nullptr
while(head->next!=NULL)
{
node* temp1=head;
node* temp2=head; // Choose better names
while(temp1->next!=NULL) // Traverse the entire list at every iteration
{
temp2=temp1;
temp1=temp1->next;
}
if(flag==0)
{
head1=temp1;
flag++;
}
temp1->next=temp2; // Always and only swaps the last two elements
temp2->next=NULL;
// Never updates head in the loop; loop is infinite
}
head=head1;
delete head1; // head1 was pointing to a valid node; you just nuked your
// entire list
}
The algorithm is quite simple, and one that reveals itself when the problem is drawn using paper and pencil. You just need to make the arrows point the other way, and reassign the head. You are attempting that, but you don't change any pointers except for the final two nodes. You need to be changing them as you move through the list.
The special head check and flag are unnecessary. You will naturally arrive at the tail and can reassign head when you do so.
Here's the reworked algorithm:
#include <iostream>
struct node {
int data;
node* next;
node(int d) : data(d), next(nullptr) {}
};
//
// Bigger issues implied by this function is that it is not a very good
// linked list, likely an extremely basic C-style list. However, that is
// beyond the scope of this question.
//
void rev(node*& head) {
node* prev = nullptr;
node* curr = head;
node* next = nullptr; // Not immediately assigned to account for
// empty list.
while (curr) {
next = curr->next; //
curr->next = prev; // This order of operations is very important
prev = curr; //
curr = next; //
}
head = prev;
}
int main() {
node* list = new node{1};
list->next = new node{2};
list->next->next = new node{3};
list->next->next->next = new node{4};
list->next->next->next->next = new node{5};
node* walker = list;
std::cout << "Original list: ";
while (walker != nullptr) {
std::cout << walker->data << ' ';
walker = walker->next;
}
std::cout << '\n';
rev(list);
std::cout << "Reversed list: ";
walker = list;
while (walker != nullptr) {
std::cout << walker->data << ' ';
walker = walker->next;
}
std::cout << '\n';
// On the one hand, I don't delete my nodes. On the other,
// the program is ending and the OS will clean up my mess.
// This is generally a bad practice.
}
Output:
❯ ./a.out
Original list: 1 2 3 4 5
Reversed list: 5 4 3 2 1
While it would require more code, a proper C++ linked list class would be strongly preferred to avoid the downright silly initialization required in main().
And I understand that this code is likely just to understand this particular algorithm, but the C++ standard library does provide both singly and doubly linked lists, both of which are trivial to reverse.

Reversing a linked list starting from the tail using recursion

I still struggle with the recursion technique to solve the problem. I know there are nicer ways to solve my problem below of reversing a linked list. Most of the ways that I have seen, start to reverse the pointers by going from the head to the tail, either by using iteration or recursion.
I am trying for interest to reverse the list by first finding the last node in the list recursively and then changing the pointers everytime the function returns.
What am I doing wrong below exactly? Or will this method even work , without the need to pass more parameters to the recursive function? Thanks in advance for your help.
struct Node
{
int data;
struct Node *next;
};
Node* Reverse(Node *head)
{
static Node* firstNode = head;
// if no list return head
if (head == NULL)
{
return head;
}
Node* prev = NULL;
Node* cur = head;
// reached last node in the list, return head
if (cur->next == NULL)
{
head = cur;
return head;
}
prev = cur;
cur = cur->next;
Reverse(cur)->next = prev;
if (cur == firstNode)
{
cur->next = NULL;
return head;
}
return cur;
}
EDIT : Another attempt
Node* ReverseFromTail(Node* prev, Node* cur, Node** head);
Node* ReverseInit(Node** head)
{
Node* newHead = ReverseFromTail(*head, *head, head);
return newHead;
}
Node* ReverseFromTail(Node* prev, Node* cur, Node** head)
{
static int counter = 0;
counter++;
// If not a valid list, return head
if (head == NULL)
{
return *head;
}
// Reached end of list, start reversing pointers
if (cur->next == NULL)
{
*head = cur;
return cur;
}
Node* retNode = ReverseFromTail(cur, cur->next, head);
retNode->next = cur;
// Just to force termination of recursion when it should. Not a permanent solution
if (counter == 3)
{
cur->next = NULL;
return *head;
}
return retNode;
}
Finally Solved it :
Node* NewestReverseInit(Node* head)
{
// Invalid List, return
if (!head)
{
return head;
}
Node* headNode = NewestReverse(head, head, &head);
return headNode;
}
Node* NewestReverse(Node *cur, Node* prev, Node** head)
{
// reached last node in the list, set new head and return
if (cur->next == NULL)
{
*head = cur;
return cur;
}
NewestReverse(cur->next, cur, head)->next = cur;
// Returned to the first node where cur = prev from initial call
if (cur == prev)
{
cur->next = NULL;
return *head;
}
return cur;
}
I will not give you the code, I will give you the idea. You can implement the idea in the code.
The key to all recursion problems is to figure out two cases: repetition step and end case. Once you do this, it works almost as if magically.
Applying this principle to reversing a linked list:
End case: the list of one element is already reversed (this is straightforward) and returning the element itself
Repetition case: Given list L, reversing this least means reversing an L', where L' is the L' is the list without the very first element (usually called head), and than adding the head as the last element of the list. Return value would be the same as a return value of the recursive call you just made.
It can be done. The key in understanding recursion is What is the starting point?
Usually I create a "starting" function which prepares the first call. Sometimes it is a separate function (like in non OO implemnatation at bottom). Sometimes it's just a special first call (like in example below).
Also the key is in remembering variables before they change and what is the new head.
The new head is the last element of the list. So You have to get it up from the bottom of the list.
The nextelement is always your parent.
Then the trick is to do everything in the correct order.
Node* Reverse( Node* parent) // Member function of Node.
{
Node* new_head = next ? next->Reverse( this )
: this;
next = parent;
return new_head;
}
You call the function with: var.Reverse( nullptr);
Example:
int main()
{
Node d{ 4, nullptr };
Node c{ 3, &d };
Node b{ 2, &c };
Node a{ 1, &b };
Node* reversed = a.Reverse( nullptr );
}
So what is happening here?
First we create a linked list:
a->b->c->d->nullptr
Then the function calls:
a.Reverse(nullptr) is called.
This calls the Reverse on the next node b.Reverse with parent a.
This calls the Reverse on the next node c.Reverse with parent b.
This calls the Reverse on the next node d.Reverse with parent c.
d doesn't have next node so it says that the new head is itself.
d's next is now it's parent c
d returns itself as the new_head.
Back to c: new_head returned from d is d
c's next is now it's parent b
c returns the new_head it recieved from d
Back to b: new_head returned from c is d
b's next is now it's parent a
b returns the new_head it recieved from c
Back to a: new_head returned from b is d
a's next is now it's parent nullptr
a returns the new_head it recieved from b
d is returned
Non object oriented implementation;
Node* reverse_impl(Node* parent)
{
Node* curr = parent->next;
Node* next = curr->next;
Node* new_head = next ? reverse_impl( curr )
: curr;
curr->next = parent;
return new_head;
}
Node* reverse(Node* start)
{
if ( !start )
return nullptr;
Node* new_head = reverse_impl( start );
start->next = nullptr;
return new_head;
}
Here's a full implementation I wrote in 5 minutes:
#include <stdio.h>
struct Node
{
int data;
struct Node *next;
};
struct Node* Reverse(struct Node *n)
{
static struct Node *first = NULL;
if(first == NULL)
first = n;
// reached last node in the list
if (n->next == NULL)
return n;
Reverse(n->next)->next = n;
if(n == first)
{
n->next = NULL;
first = NULL;
}
return n;
}
void linked_list_walk(struct Node* n)
{
printf("%d", n->data);
if(n->next)
linked_list_walk(n->next);
else
printf("\n");
}
int main()
{
struct Node n[10];
int i;
for(i=0;i<10;i++)
{
n[i].data = i;
n[i].next = n + i + 1;
}
n[9].next = NULL;
linked_list_walk(n);
Reverse(n);
linked_list_walk(n+9);
}
Output:
0123456789
9876543210

Merging 2 linked lists and appending to the end of linked lists c++

I don't have much so far but I am trying to get the hang of using linked lists.
Struct:
struct Node
{
int value;
Node *next;
};
How can I add a node to the end of the list? I am just trying to take in a pointer for the head of a list and an int value to add in as a new node. When I try running what I have currently I get an exception.
void addNode(Node* head, int x)
{
Node* temp = new Node;
temp->data = x;
temp->next = NULL;
if(!head)
{
head = temp;
return;
}
else
{
Node* last = head;
while(last->next)
last=last->next;
last->next = temp;
}
}
I haven't really begun to work on merging the two lists. I just know that I need to take in 2 linked lists (or pointers to the head of 2 linked lists?) and then run through the lists for all the nodes.
E.G: Linked list 1 has 3 nodes: 4, 10, 20.
Linked List 2 has 4 nodes: 2, 5, 15, 60.
The merge list function would results in a new linked list with 2,4,5,10,15,20,60 as the nodes.
EDIT: In my main, I am calling the addNode function like so:
Node *head = new Node;
insertAtEnd(head,20);
Is that correct or could that be the cause of the exception?
By doing this:
void addNode(Node* head, int x)
// here ---------^
and then later this:
head = temp; // here
you're simply modifying the local head pointer, which took on the address value passed from the caller. Since head is not an actual reference to a pointer (it's just a pointer), the result is the caller's pointer passed as head remains unaltered. You never append your allocated node to your list, leak memory, it becomes a sad day...
Pass the pointer by reference instead. Fixing that, then fixing the invalid data member, which should actually be value and a pointer-to-pointer for walking the list to find the end, the result could look something like this:
#include <iostream>
struct Node
{
int value;
Node *next;
};
void addNode(Node*& head, int x)
{
Node **pp = &head;
while (*pp)
pp = &(*pp)->next;
*pp = new Node;
(*pp)->value = x;
(*pp)->next = nullptr;
}
void printList(const Node *head)
{
for (; head; head = head->next)
std::cout << head->value << ' ';
std::cout << '\n';
}
void freeList(Node *&head)
{
while (head)
{
Node *p = head;
head = p->next;
delete p;
}
}
int main()
{
Node *head = nullptr;
for (int i=1; i<=5; ++i)
addNode(head, i);
printList(head);
freeList(head);
}
Output
1 2 3 4 5
I leave the task of implementing an actual merge to you, but this should be enough to get you a manageable list up and running.
Update: From the OP's edited question:
Node *head = new Node;
insertAtEnd(head,20);
Apart from now-being a completely different named function, your node is default-initialized. In your case that means the resulting Node from new Node; has indeterminate values for both value and next. You're then passing that to your function, which assumes a determinate value (null) to terminate your loop.
This can be fixed any number of ways; the mechanics of the code above is one such way. There is no need to pre-allocate a head node in the first place if the list management code is of the understanding that NULL means no-list. Your addNode original post seemed to at-least-try to follow that mantra.
Declare the function the following way
void addNode( Node* &head, int x) ;
And instead of this code snippet
Node *head = new Node;
insertAtEnd(head,20);
You have to call the function the first time the following way
Node *head = nullptr; // or NULL
addNode(head,20);
Notice that there is no function with name insertAtEnd in your post. There is function addNode.:)
If you need to merge two lists then you can use this demonstrative program as a sample. Of course you will need to add some other functions as for example deleting lists that to get a complete project.
#include <iostream>
struct Node
{
int value;
Node *next;
};
Node * insert( Node *current, int value )
{
Node *tmp;
if ( current == nullptr )
{
tmp = new Node { value, nullptr };
}
else
{
tmp = new Node { value, current->next };
current->next = tmp;
}
return tmp;
}
std::ostream & display( Node *head,
std::ostream &os = std::cout,
const char *delimiter = " " )
{
for ( ; head; head = head->next ) os << head->value << delimiter;
return os;
}
Node * merge( Node * &head1, Node * &head2 )
{
Node *new_head = nullptr;
Node *current = nullptr;
while ( head1 != nullptr && head2 != nullptr )
{
Node *tmp;
if ( head2->value < head1->value )
{
tmp = head2;
head2 = head2->next;
}
else
{
tmp = head1;
head1 = head1->next;
}
tmp->next = nullptr;
if ( new_head == nullptr )
{
new_head = tmp;
current = new_head;
}
else
{
current->next = tmp;
current = current->next;
}
}
if ( head1 != nullptr ) new_head == nullptr ? new_head : current->next = head1;
if ( head2 != nullptr ) new_head == nullptr ? new_head : current->next = head2;
head2 = nullptr;
head1 = new_head;
return new_head;
}
int main()
{
Node *list1 = nullptr;
Node *list2 = nullptr;
list1 = insert( list1, 4 );
insert( insert( list1, 10 ), 20 );
display( list1, std::cout << "List1: " ) << std::endl;
list2 = insert( list2, 2 );
insert( insert( insert( list2, 5 ), 15 ), 60 );
display( list2, std::cout << "List2: " ) << std::endl;
std::cout << std::endl;
merge( list1, list2 );
display( list1, std::cout << "List1: " ) << std::endl;
display( list2, std::cout << "List2: " ) << std::endl;
return 0;
}
The program output is
List1: 4 10 20
List2: 2 5 15 60
List1: 2 4 5 10 15 20 60
List2:
this may be a cause of exception:
struct Node
{
int value; <----- Node structure has value property
Node *next;
};
Node* temp = new Node;
temp->data = x; <------ Assigning to data property of Node which does not exists
temp->next = NULL;
To add list you may use same approach
void addNode(Node* head, Node* head2)
{
Node* last = head;
while(last->next) last=last->next;
last->next = head2;
}
EDIT: In my main, I am calling the addNode function like so:
Node *head = new Node;
insertAtEnd(head,20);
This is wrong. You didn't initialize head->next, so within insertAtEnd the code while(last->next) last=last->next; will attempt to compare uninitialized pointer and if it isn't null, will dereference it. This will likely crash your program rather than throw an exception though. Then again, it's undefined behaviour, so anything may happen.
Since your insert function already covers the case of inserting to empty list, I would simply call
head = nullptr;
insertAtEnd(head,20)`;
Besides that, there's the bug of never updating the head pointer outside the function, which has already been covered in other answers.

Vector elements inserted into a linked list?

I'm trying to create a function which take in a Vector of Tokens, which is a type defined by my professor, and enter each element of the vector into the linked list, I return the head of the first element. The cout statement in the last part of new_list shows that I am indeed inserting the elements of the vector into the linked list. So when I type in:
new a 9 2 3
9 2 3 are being inserted
The print_list_cmd is defined by my professor and is supposed out the list that I created by calling new a,
so,
print a should return
9 2 3
but when I type print I only get the last element of the linked list which is 3.
I have two questions my code is not very elegant is there a better way to insert a vector of tokens into a linked list? Two why is the print command only returning the last element in the linked list? Also there is a lexer class that tokenizes the input but it's alot of code so I didn't insert it, if it's helpful or you need me to insert it I will.
struct Node {
int key;
Node* next;
Node(int k=0, Node* n=NULL) : key(k), next(n) {};
};
Node* new_list(const vector<Token>& tok_vec){
//int key;
Node *head;
Node *newHead;
Node *headPointer = NULL;
newHead = new Node;
newHead -> next = NULL;
head = NULL;
for(unsigned int i = 0 ; i < tok_vec.size() ; i++){
// newHead -> key = tok_vec.at(i).value;
string myStream = tok_vec.at(i).value;
istringstream buffer(myStream);
int value;
buffer >> value;
newHead -> key = value;
if(!head){
head = newHead;
}else{
headPointer = newHead;
while(headPointer -> next){
headPointer = headPointer -> next;
headPointer -> next = newHead;
}
}
cout << head->key << endl;
}
return head->key;
}
void print_list_cmd(Lexer lex){
Token tok = lex.next_token();
if (tok.type != IDENT || lex.has_more_token())
throw runtime_error("SYNTAX: print listname");
if (list_table.find(tok.value) == list_table.end())
throw runtime_error(tok.value + " not defined or already destroyed");
print_list(list_table[tok.value]);
}
Looking at your code, you don't return the head of the list, you return the value from the head Node:
return head->key;
instead of:
return head;
Also, most effective way to insert new items into the list would be inserting them at the head:
/// inserts node at the head of the list and returns the new head;
Node* insertNode(int key, Node* head) {
Node* newHead = new Node;
newHead->key = key;
newHead->next = head;
return newHead;
}
you could use that as:
Node* new_list(const vector<Token>& tok_vec){
Node* head = NULL;
for(unsigned int i = 0 ; i < tok_vec.size() ; i++){
string myStream = tok_vec.at(i).value;
istringstream buffer(myStream);
int value;
buffer >> value;
head = insertNode(value, head);
///
}
return head;
}
UPDATE. the resulting list will be backwards with regard to the input, so you would have to reverse it. One of the possibilities would be to create another list from the original one, so that at the end the last element of the old list will be the head of the new one:
Node* reverse(Node* list) {
Node* reversed = NULL;
while (list!=NULL) {
Node* nextNode = list;
list = list->next;
nextNode->next = reversed;
reversed = nextNode;
}
return reversed;
}

Single Sorted Linked List - Infinite Loop

I'm working with a single linked list and I want to sort it from lower to higher values of integer. I though I had the idea but then the execution enters in a infinite loop and I can't see clearly why. This is the part of the code I worked with:
class Node {
int data;
Node* next;
public:
Node() { };
void SetData(int aData) { data = aData; };
void SetNext(Node* aNext) { next = aNext; };
int Data() { return data; };
Node* Next() { return next; };
};
class List {
Node *head;
public:
List() { head = NULL; };
void Print();
void Append(int data);
void Delete(int data);
};
void List::Append(int data) {
// Create a new node
Node* newNode = new Node();
newNode->SetData(data);
newNode->SetNext(NULL);
// Create a temp pointer
Node *tmp = head;
if ( tmp != NULL ) {
// Nodes already present in the list
// Parse to end of list anytime the next data has lower value
while ( tmp->Next() != NULL && tmp->Next()->Data() <= newNode->Data() ) {
tmp = tmp->Next();
}
// Point the lower value node to the new node
tmp->SetNext(newNode);
newNode->SetNext(tmp->Next());
}
else {
// First node in the list
head = newNode;
}
}
void List::Print() {
// Temp pointer
Node *tmp = head;
// No nodes
if ( tmp == NULL ) {
cout << "EMPTY" << endl;
return;
}
// One node in the list
if ( tmp->Next() == NULL ) {
cout << tmp->Data();
cout << " --> ";
cout << "NULL" << endl;
}
else {
// Parse and print the list
do {
cout << tmp->Data();
cout << " --> ";
tmp = tmp->Next();
}
while ( tmp != NULL );
cout << "NULL" << endl;
}
}
I'm confused if the list increases infinitely or the error comes from the Print function...
Sorry for the, perhaps, dummy errors.
Thanks.
Your problem is these two lines:
tmp->SetNext(newNode);
newNode->SetNext(tmp->Next());
You should reverse them. Right now, you set tmp.next = newNode, and then newNode.next = tmp.next (= newNode), so newNode points to itself. Then traversing past newNode leads to an infinite loop.
You are failing to link two existing nodes properly. Look at this fragment of your code:
tmp->SetNext(newNode);
newNode->SetNext(tmp->Next());
If for example you have this list:
head -> 5
and you want to insert a node with number 4 you will have:
head -> 5 <- tmp
newNode -> 4
With tmp->SetNext(newNode)
head (and tmp) -> 5 -> 4 <- newNode
With newNode->SetNext(tmp->Next());
head (and tmp) -> 5 -> 4 <- newNode
So any attempt to iterate through the list will result in and infinite loop:
5
4
4
4
4 ...... forever
// Point the lower value node to the new node
tmp->SetNext(newNode);
newNode->SetNext(tmp->Next());
Since you overwrite tmp->next in the first call, your second call is actually pointing newNode->next towards newNode itself, creating a cycle. This causes your infinite loop when calling Print ;-)
The solution is to do something like as follows...
Node* _next = tmp->Next();
tmp->SetNext(newNode);
newNode->SetNext(_next);
That being said, your code is still broken. The problems is that you don't check whether you need to place before the head of the list; try doing something as follows..
if ( tmp ) {
// Check whether to become new head
if ( tmp->Data() > newNode->Data() ) {
newNode->SetNext(tmp);
head = newNode;
}
else {
// Nodes already present in the list
// Parse to end of list anytime the next data has lower value
while ( tmp->Next() && tmp->Next()->Data() <= newNode->Data() ) {
tmp = tmp->Next();
}
// Point the lower value node to the new node
Node* _next = tmp->Next();
tmp->SetNext(newNode);
newNode->SetNext(_next);
}
}
else {
// First node in the list
head = newNode;
}
Side note: you can use an initializer list to rewrite code like...
List() : head(NULL) { };
In addition, if NULL is equivalent to 0, you can simplify conditions of the form X == NULL and X != NULL as merely X and !X, respectively.
See my ideone paste for the corrected version with an example.
int main() {
List l;
l.Append(15);
l.Append(40);
l.Append(7);
l.Print();
return 0;
}
... which produces
7 --> 15 --> 40 --> NULL