LinkedList creating nodes - c++

I tried to implement C++ singly linked. I have created a method which creates a node and add a value and points to another node but i have to remember index.
How to improve the code and create nodes without remembering index? (I want to maintain order = first created node points to another etc.)
Class method:
void LinkedList::addValue ( int val )
{
if ( ! index )
{
n = new Node();
head = n;
n->value = val;
n->next = NULL;
}
else
{
n->next = new Node( );
n = n->next;
n->value = val;
}
++index;
}

I guess, you already have two member variables: head which is the root node and n which is the last node. You should initialize both of them with NULL (nullptr for c++11) in constructor. Then you can just check if n==NULL when you add a new value to the list.
LinkedList::LinkedList():head(NULL),n(NULL)
{}
void LinkedList::addValue ( int val )
{
if (n==NULL)
{
n = new Node();
head = n;
n->value = val;
n->next = NULL;
}
else
{
n->next = new Node( );
n = n->next;
n->value = val;
}
}
The index variable, however, can be useful if you want to find the list size in one fast read operation without iterating over all its nodes.

You can create another pointer called Tail to point to the last element. That way you can add value to the list without the index.
I call this method append
void append(int val){
void append(int val) {
Node* tmp = new Node(); // creating a temporary pointer to a new node
tmp -> value = val
last -> next = tmp; // connect the new node to the linked list
last = tmp; // set the last to the newly created node
listSize++; // increase the size of the list
}
You can also improve the code by making a Constructor for the node:
Class Node{
public:
int value;
Node * next;
Node(Node * nextEle = NULL) {
next = nextEle;
}
Node(int val,Node * nextEle = NULL) {
value = val;
next = nextEle;
}
}

Related

when I execute linked list using class it shows an extra zero

#include<bits/stdc++.h>
#include<vector>
using namespace std;
class Node {
public :
int data;
Node *next;
Node()
{
data = 0;
next = NULL;
}
Node (int a)
{ data = a;
next = NULL;
}
};
void push(Node **head_ref , int n)
{
Node *new_node = new Node();
new_node -> data = n;
new_node -> next = *head_ref;
*head_ref = new_node;}
void display(Node *head_ref)
{ while(head_ref != NULL)
{
cout << head_ref -> data << " ";
head_ref = head_ref-> next;
}
}
int main()
{ Node *head = new Node();
push (&head ,1 );
push(&head ,0 );
push(&head , 1);
display(head);
return(9);}
This when executed returns 1 0 1 0 as output , First i thought it is because of constructors but later I came to know that it is not something causing the problem.
Node *head = new Node();
Creates the extra node. Instead use
Node *head = nullptr;
or, if using an older compiler,
Node *head = NULL;
to point head at a safe location until legitimate nodes are added.
In your code
Node *head = new Node();
Creates a new Node, the first one, then the other 3 nodes are created by calling the push() thrice.
Workaround? After pushing the values, do head = head->next

Problem with my doubly linked list insert function

I am trying to finish up a assignment for my data structures c++ class. I have to define a double linked list of functions(like insert() size() remove() ) that was provided by my instructor. The instructor also includes the main file which runs tests on my code to see if it works.
I'm receiving his error message:
* Starting dlist tests *
Checking empty list...
FAILED: size of empty list is != 0.
I tried to rewrite the definition of the size() and insert() function and Im not understanding why im getting his error.
my instructors test code:
bool test_empty() {
std::cout << "Checking empty list...\n";
dlist e;
if(!verify(e))
return false;
if(e.size() != 0) {
std::cout << "FAILED: size of empty list is != 0.\n";
return false;
}
if(!e.empty()) {
std::cout << "FAILED: empty list is not .empty().\n";
return false;
}
return true;
}
my code for implementations:
void insert(node *previous, int value){
if(previous == nullptr){
node* n = new node;
n->value = value;
n->prev = previous;
n->next = nullptr;
return;
}
node* n = _head; //made a pointer to start at the head
while( n!= previous )//make n go down the list until it hits previous
{n = n->next;}
node* store_next = n->next; //store the address of the prev pointer of the next node
node* a = new node;//create the node that will be inserted
a->value = value;
n->next = a;// the pointer n points to the new node
a->prev = n; //the prev in the new node points to the previous
a->next = store_next; //the next in the new node points to the next node
store_next->prev = a; //the next node's prev points to the new inserted node
}
int size() const{
node* n = _head;
int size = 0;
while(n != nullptr){
size++;
n = n -> next;
}
return size;
}
Heres my default constructor and double linked list struct that my professor requires I use
class dlist {
public:
dlist() {
}
struct node {
int value;
node* next;
node* prev;
};

Sorting linked list while inserting a node

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

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

copy constructor for a linked list classes

So I want to copy a whole linked list classes, I have trouble figuring it out how to do so,
class list{
public:
list(const list &t);
private:
struct Node{
int x;
Node *next;
}*p;
I started with something like this:
list::list(const list &t){
Node* q;
q=new Node;
while (p!=NULL){
q->x= p->x;}
}
but I'm not sure if I am on the right track or what. I also have trouble how should I test such a copy constructor? For example I have list l1, then i insert couple integers into a list and then how I can copy it?
In your example it never will work if you initialized p or will work forever if p != NULL. You must allocate new nodes while traversing through t list:
p = NULL;
Node* copy = l.p;
Node* insert = p;
Node* inserted_el = NULL;
while (copy){
insert = new Node();
insert->x = copy->x;
insert->next = NULL;
if (inserted_el) {
inserted_el->next = insert; //copy memory pointer to next element
} else {
p = insert; //copy memory pointer to list head
}
copy = copy->next;
inserted_el = insert;
}
This is basic idea. Also don't forget to implement assign operator and destructor.
Usage:
list t1;
//insert nodes
list t2(t1);
The biggest trouble in your code is that you do not duplicate each node of the list while you need to do so.
Here is the code of the ctor:
list::list(const list &t)
{
p = NULL; // Init the head of the list this is vital important.
// Loop over the elements of the passed list if any.
Node *pt = t.p;
Node *last_local_element = NULL;
while (pt != NULL)
{
// Allocate a new node and set the fields there.
Node *q = new Node;
q->x= pt->x;
     q->next = NULL;
// Add new node to the local list.
if (last_local_element != NULL) {
last_local_element->next = q;
} else {
p = q;
}
last_local_element = q;
// Shift the loop variable along the passed list.
pt = pt->next;
}
}
There are 2 most often cases when the copy ctor is called:
list my_list1;
list my_list2(my_listl); // Explicit call.
list my_list3 = my_listl; // Assignment in the definition statement.
With your design of class, you need to be careful with memory management. This is the code:
list::list(const list& t) {
Node* n = t.p;
Node* m = p;
while (n) {
if (!m) {
m = new Node(); // Allocate memory.
if (!p) p = m;
}
m->x = n->x;
m = m->next;
n = n->next;
}
if (m) { // Original list is longer, delete the rest of the list.
Node * tmp = m;
m = m->next;
delete tmp;
}
}