Could anyone tell me if this is the basic idea of linked lists? What are the pros and cons to this method and what are best practices when implementing linked lists in C++? Im new to data structures so this is my first approach. If there is a better way to do this same thing, please let me know. Additionally, how would you create the nodes dynamically without hard coding it? Thanks.
#include <iostream>
#include <string>
using namespace std;
struct node {
int x;
node *next;
};
int main()
{
node *head;
node *traverser;
node *n = new node; // Create first node
node *t = new node; // create second node
head =n; //set head node as the first node in out list.
traverser = head; //we will first begin at the head node.
n->x = 12; //set date of first node.
n->next = t; // Create a link to the next node
t->x = 35; //define date of second node.
t->next = 0; //set pointer to null if this is the last node in the list.
if ( traverser != 0 ) { //Makes sure there is a place to start
while ( traverser->next != 0 ) {
cout<< traverser->x; //print out first data member
traverser = traverser->next; //move to next node
cout<< traverser->x; //print out second data member
}
}
traverser->next = new node; // Creates a node at the end of the list
traverser = traverser->next; // Points to that node
traverser->next = 0; // Prevents it from going any further
traverser->x = 42;
}
for tutorial purpose, you can work out this example:
#include <iostream>
using namespace std;
struct myList
{
int info;
myList* next;
};
int main()
{
//Creation part
myList *start, *ptr;
char ch = 'y';
int number;
start = new myList;
ptr = start;
while (ptr != NULL)
{
cout << "Enter no. ";
cin >> ptr->info;
cout << "Continue (y/n)? ";
cin >> ch;
if (ch == 'y')
{
ptr->next = new myList;
ptr = ptr->next;
}
else
{
ptr->next = NULL;
ptr = NULL;
}
}
//Traversal part begins
cout << "Let's start the list traversal!\n\n";
ptr = start;
while (ptr!=NULL)
{
cout << ptr->info << '\n';
ptr = ptr->next;
}
}
It allocates memory dynamically for as many elements as you want to add.
I'd prefer to make a linked list class. This eliminates the need to call 'new' more than once. A nice implementation with examples can be found here.
You are in fact already doing dynamic allocation. So, not sure what you are asking for. But if you want to define functions to add new nodes to your linked list (or delete a node etc.), this can be a probable solution:
The location nodes get inserted/deleted is dependent on the type of data-structure. In a queue, new nodes will get added to the end; at the top in case of a stack. A function that adds a node to the top, simulating STACK push operation:
void pushNode(node **head, int Value) {
node *newNode = new node;
newNode->x = Value;
newNode->next = *head;
*head = newNode;
}
It would be called like pushNode(&head, 15) where 'head' would be defined as node *head = NULL. The root head should initially be set to NULL. After this operation head will point to the newly added node (top of stack).
The approach would be very similar for other data-structures (viz. queues) and works fine. But as you are using C++, I would suggest to define a class for your linked-list and define these functions as methods. That way, it will be more convenient and less error-prone.
Even better use std::list. It's the standard thing, so much portable and robust than a custom implementation.
You can also do it in this way
#include <iostream>
using namespace std;
struct Node{
int data;
Node* next;
};
void createList(Node** head ,Node* temp){
int n;
char ch;
temp = *head;
while(temp != NULL){
cout<<"Enter The Value ";
cin>>temp->data;
cout<<"DO you want to continue(y/n)";
cin>>ch;
if(ch=='Y' || ch == 'y'){
temp->next = new Node;
temp = temp->next;
}else{
temp->next = NULL;
temp = NULL;
}
}
}
void ShowList(Node* head){
cout<<"your list :"<<endl;
while(head != NULL){
cout<<head->data<<" ";
head = head->next;
}
}
int main()
{
//Creation part
Node *head, *temp;
createList(&head,temp);
ShowList(head);
}
Related
I'm trying to transition from an almost entirely Java background to getting comfortable with C++. I'm practicing by trying to build a basic Linked List.
#include <iostream>
#include <string>
using namespace std;
struct node
{
string data;
node *next = NULL;
};
class linkedlist
{
public:
node *head;
public:
linkedlist()
{
head = NULL;
}
void addNode(string s)
{
node *newNode = new node;
newNode->data = s;
if(head == NULL)
head = newNode;
else
{
node *temp = head->next;
while(temp != NULL)
temp = temp->next;
temp = newNode;
}
}
void printList()
{
node *temp = head;
while(temp != NULL)
{
cout << temp->data << '\n';
temp = temp->next;
}
}
};
The issue at hand is that once I add a new node using void addNode(string s), it does not appear when I attempt to print the list (starting from the head) with void printList().
For example:
int main(int argc, const char * argv[])
{
int n;
string str;
linkedlist list;
cout << "Please enter the number of strings you'd like to enter:\n";
cin >> n;
for(int i = 0;i < n;i++)
{
string temp;
cout << "Enter string #" << i + 1 << '\n';
cin >> temp;
list.addNode(temp);
}
cout << "This is your linked list: ";
list.printList();
return 0;
}
Using main() above, my results become:
This is your linked list:
(string 1)
I'm pretty certain I'm using pointers improperly here but I don't see why. I've done as much digging as I can on my own for some clarification on how I could be doing this wrong but I'm coming up blank.
Thanks for any clarification you folks can provide.
The problem is here:
node *temp = head->next;
while(temp != NULL)
temp = temp->next;
temp = newNode;
You're traversing the list, then setting temp to the value of the newNode. When temp goes out of scope, the value for newNode isn't stored anyplace.
What you want to do is set the next pointer of the last node to the value of newNode, i.e.
node *temp = head;
while(temp->next != NULL)
temp = temp->next;
temp->next = newNode;
The code above traverses the list until it finds a node that doesn't have a next node, and sets its next node to the newNode, thus adding it to the list.
I'm trying to create a linked list from user input but it's not printing anything when i try to print it. Not even the head. Also note, it is intentionally backwards.
Here is my function for getting user input, it returns the list. I know it is wrong but i've spent hours on it and can't get it to work...
#include <iostream>
#include <limits>
#include <ios>
struct Node {
int value;
Node *next;
}
Node* getInput() {
Node* head = nullptr;
Node* tmp;
while (true) {
int x;
if (!(cin >> x)) {
break;
} else if ( head == nullptr) {
head = new Node{x, nullptr);
} else {
tmp = new Node{x , nullptr};
tmp->next = head;
head = head->next;
}
}
return tmp;
}
int main() {
cout << getInput()->value;
}
A couple of good solutions up, but because the request was for a backward list, this can be really, really simple.
Node* getInput()
{
Node* head = nullptr;
int x;
while (std::cin >> x) // keep going until we can't get a good x.
{
head = new Node{x, head}; // point node at current head, assign new head
// head always points at the beginning of list because items are
// always inserted at the start of the list.
}
return head;
}
So to prove this list prints backward, here's a simple tester
int main()
{
Node* cur = getInput();
while (cur)
{
std::cout << cur->value << '\n';
cur = cur->next;
}
}
The return value of get input() is not the actual head/start of the list. Head will always point to null the moment you insert any node. Head value can be stored in a temporary pointer during first insert and return temporary pointer instead of head.
If you are trying to print the linked list in reverse order, here's a working version:
#include <iostream>
#include <limits>
#include <ios>
using namespace std;
struct Node {
int value;
Node *next;
Node(int val, Node *nextPtr) {
value = val;
next = nextPtr;
}
};
Node *getInput() {
Node *head = nullptr;
Node *tmp;
while (true) {
int x;
if (!(cin >> x)) {
break;
} else if (head == nullptr) {
head = new Node(x, nullptr);
} else {
tmp = new Node(x, nullptr);
tmp->next = head;
head = tmp;
}
}
return head;
}
int main() {
Node *head = getInput();
Node *tmp;
while (head != nullptr) {
cout << head->value << ", ";
tmp = head;
head = head->next;
delete tmp;
}
cout << endl;
return 0;
}
head = head->next; is the problem. You're allocating a Node correctly, but you immediately leak that Node and head is pointing to nullptr.
The simplest solution is to keep head pointed at the most recent Node. You'll need a special case for the first insertion since head will be uninitialized (fix that by the way), but that way you're always pointing at the most recent Node.
If you have trouble, draw your Nodes out on paper with arrows. Watch how the arrows change at each insertion, and you'll see what's happening.
I have managed to create a simple insertion at beginnning of linked list program but now i am struggling with insertion at end of linked list.
The program seems to be able to take values from user but the output list is not coming correct.Could you help me out?
If possible keep along the lines of my program as i am beginner and won't be able to understand a completely different method.
Logic i used-
If list is empty then insert value at beginning else if list is not empty then travel along the list till the next value being pointed at is NULL and then enter the new value in place of NULL.
#include<iostream>
using namespace std;
struct node
{
int data;
node *next;
};
node *start=NULL;
void insertend(int x)
{
node* temp=new node;
if(start==NULL)
temp->data=x;
else
{
while(temp!=NULL)
{
temp=temp->next;
}
temp->next=x;
}
}
void display()
{
node* disp=new node;
while(disp!=NULL)
{
cout<<disp->data<<endl;
disp=disp->next;
}
}
int main()
{
int x;
char ch;
do
{
cout<<"Enter data";cin>>x;
cout<<endl;
insertend(x);
cout<<"Do you want to continue?(y/n)";cin>>ch;
cout<<endl;
}while(ch=='y');
cout<<"Your list:"<<endl;
display();
}
The entry point to your list is the variable start. But you never set it. Take for example the first item a user inputs. You will call insertend(), it will check that start == NULL, but then it never sets start. You must set start = temp or something similar. You have the same problem in the else section -- you loop through the nodes starting with temp, but you should be starting with start. And again in the function display(), you create a pointer to a node and start looping from it, but it will have no data -- you should use start as the starting point of your loop.
struct node{
int data;
node* next;
};
node *first = NULL, *last = NULL;
void insert(int x){
if(first == NULL){
first = new node;
first->data = x;
first->next = NULL;
}else if(last == NULL){
last = new node;
last->data = x;
first->next = last;
last->next = NULL;
}else{
node *n = new node;
n->data = x;
n->next = NULL;
last->next = n;
last = n;
}
}
As you can see I am keeping track of first and last node in the list. Insert function checks if there is anything in the list with if(first == NULL)part. If there isn't it creates the first node. Similar thing happens with the else if. Finally in the else block we create a new node with data x. Then point the node stored in variable last to our new node and set last to be that node.
Here is the display function:
void display()
{
node *disp =first;
while(disp->next != NULL){
cout << disp->data << " ";
disp = disp->next;
}
cout << disp->data;
}
I also recommend that you do a cleanup after your program is finished running since you are creating new nodes.
void cleanup(node* n)
{
if(n->next == NULL)return delete n;
cleanup(n->next);
delete n;
}
and then at the end of main call cleanup(first)
Hope this makes sense :) Have a nice day!
I am a beginner in C++ and need help in many things. Well, for the starters, I have been working on Linked List and not really getting why my header(the first pointer which points towards first node) keep on rotating. I am just pointing it towards first node plus my display node is just displaying last node, why is it so?. Please tell me where I am wrong. Thank you in advance
#include <iostream>
#include <conio.h>
using namespace std;
struct Node
{
int data;
Node *link;
};
Node* create_Node()
{
int no_of_nodes;
Node *header = new Node;
Node *ptr = new Node;
header = ptr;
cout << "Enter no of nodes:";
cin >> no_of_nodes;
cout << "Enter data:";
for(int n = 0; n < no_of_nodes; n++)
{
cin >> ptr->data;
Node *temp = new Node;
ptr->link = temp;
temp = ptr;
}
ptr->link = NULL;
return ptr;
}
void display_link_list(Node * list)
{
Node *temp = new Node;
temp = list;
while(temp != NULL)
{
if(temp->link != NULL)
{
cout << "List:" << list->data << endl;
temp = temp->link;
}
}
}
int main()
{
Node *n = new Node;
n = create_Node();
display_link_list(n);
getch();
return 0;
}
Welcome to C++. My advice here is to break the Linked list into two. First the Nodes and then a List struct.
struct Node
{
int data;
Node *next;
Node(int data) : data(data), next(NULL) {}
};
struct List {
Node* tail;
Node* head;
List() : head(NULL), tail(NULL) {}
void insert(int data) {
if(head==NULL) {
head = new Node(data);
tail = head;
} else {
tail->next = new Node(data);
tail = tail->next;
}
}
};
Now you can insert one element into the list at a time and use head to print the list from beginning to end.
Something basic that you need to understand:
When you do Node* p = new Node, you are setting variable p to point to the start address of a piece of memory, the size of which being equal to sizeof(Node).
Now, when you then do p = something else (which often appears in your code), you are essentially overriding the previous value of p with some other value. It is like doing:
int i = 5;
i = 6;
So your code does not do what you're expecting to begin with.
In addition to that, what's bad about overriding the first value with a second value in this case, is the fact that the first value is the address of a dynamically-allocated piece of memory, that you will need to delete at a later point in your program. And once you've used p to store a different value, you no longer "remember" that address, hence you cannot delete that piece of memory.
So you should start by fixing this problem in each of the following places:
Node *header = new Node; // Variable 'header' is assigned
header = ptr; // Variable 'header' is reassigned
Node *temp = new Node; // Variable 'temp' is assigned
temp = list; // Variable 'temp' is reassigned
Node *n = new Node; // Variable 'n' is assigned
n = create_Node(); // Variable 'n' is reassigned
#include <iostream>
using namespace std;
struct Node
{
int item; // storage for the node's item
Node* next; // pointer to the next node
};
Node* addNode(Node*& head, int data , int& count)
{
Node * q; // new node
q = new Node; // allocate memory for the new mode
q->item = data; // inserting data for the new node
q->next = head; // point to previous node ?? how would i do that? ( am i doing it correctly?)
count++; // keep track of number of node
head = q;
return q;
}
int main()
{
int a, count=0;
int data;
bool repeat;
Node *head= NULL;
//^^ assuming thats creating the first node ^^
do
{
cout << "please enter the data for the next node" <<endl;
cin >> data;
addNode(head, data, count);
cout << "do you wish to enter another node? (enter true or false)" << endl;
cin >>repeat;
}
while (repeat == true);
// assuming this is the print function
while(head != NULL)
{
cout << "output" << temp->item << endl;
cout << temp->next << endl;
}
system("pause");
return 0;
}
okey i tried adding a new element in the list how would i move the head around like a LIFO memory (stack) so the last element is on the very top..
any help would be appreciated ! The pointers and the nodes are messing with my brain lately ....
temp is an uninitialized pointer. So -
temp-> item = a; // temp is not initialized or pointing to a memory location
// that has Node object to use operator ->
First, temp needs to be allocated memory location using new.
temp = new Node;
temp -> item = a;
And now assign it head. Similarly allocate memory for the child nodes too in the while loop. And return all the resources acquired from child to head using delete before program termination.
You seem to have some misunderstandings here:
Your "head" is the start of the list. It's always the start.
You add append elements to a linked list by assigning them to the last node's next pointer.
Third, you're not allocating anything.
Node *head= new Node();
Node *temp = new Node();
cout<<"enter something into data"<<endl;
cin >> a ;
temp->item = a;
head->next = temp;
Now ... to add the next thing, you either need to keep track of the last node (tail), or traverse the list to find the last node.
Node *nextNode = new Node();
nextNode->item = 0.0;
Node *i;
for (i = head; i->next != null; i = i->next);
i->next = nextNode;
This is O(n) execution time. By keeping track of the tail you make it O(1):
Node *head= new Node();
Node *tail = head;
Node *temp = new Node();
cout<<"enter something into data"<<endl;
cin >> a ;
temp->item = a;
tail->next = temp;
tail = temp;
Node *nextNode = new Node();
nextNode->item = 0.0;
tail->next = nextNode;
tail = nextNode;
EDIT: As pointed out, if you want to prepend to the list, you would:
temp->next = head;
head = temp;
Since I'm not sure every answer completely answers it, here's a linked list implementation (written without testig:
// your (correct) structure
struct Node
{
float item; // storage for the node's item
Node* next; // pointer to the next node
};
Now we need two pointers somewhere to look after the list:
/* some pointers */
struct List
{
Node* head;
Node* tail;
};
Now we need to create some elements. As others have said, you can do that with new:
/* create some elements we want to link in */
Node* elem1 = new Node();
Node* elem2 = new Node();
Node* elem3 = new Node();
/* maybe even set their properties! */
elem1->item = 3.14;
elem2->item = 3.14;
elem3->item = 3.14;
Notice how I didn't try to add these elements to a list yet? That's because I've got a function in mind which looks like this:
void addtolist(List &list, Node* node)
{
/* if no head, initialise the list */
if ( list->head == NULL )
{
list->head = node;
list->tail = node;
}
else if ( list->head != NULL && list->tail != NULL )
{
/* access the tail element and set its
next to this ptr.
Move tail to this node */
list->tail->next = node;
list->tail = node;
}
else
{
/* probably raise an exception! */
}
}
You can call this by doing this:
List l;
addtolist(l, elem1); /* etc */
Deleting elements is somewhat more tricky, since you have to go to that element, remember its previous element, grab it's next element, join them up and delete the Node* you're on.
Now for traversing lists... your terminology HEAD|TAIL reminds me of Erlang and tail recursion, where the current element is referred to as the head and the remainder the tail. If I write:
Node* cur = l.head;
while ( cur != NULL )
{
// do something with cur.item ?
cur = cur->next;
}
You can see this happening. Replacing cur with head here would be harmless thanks to the List struct.
Finally, I've used a very C-like approach here, but there's scope for templates:
template<typename T>
struct node
{
T item; // storage for the node's item
Node<T>* next; // pointer to the next node
};
and encapsulating the List struct as a class:
template<typename T>
class List
{
protected:
Node<T>* head;
Node<T>* tail;
public:
void addtolist(Node<T>* node);
Node<T>* gethead();
Node<T>* gettail();
}
Which brings you a little bit closer to std::list.
Additionally note that you are doing an implicit cast from int to float on
temp-> item = a;
as a is an int, while temp->item is a double.
To solve your problem: You want to allocate a new structure before accessing temp, thus
temp = new Node();