C++ Linked list - c++

I'm trying to make linked list similar too the one here:
linked list in C
That is to have the "head", I called it first, inside another struct. However I found doing that change. Makes it hard to add values to the list_item struct. I have tried some few things to see if it works. It compiles, however when I run the code it will crash. Any help would be helpful here. I know the cause of the crash is when I want to point the new_node to the linked_list.
#include <iostream>
using namespace std;
struct list_item
{
int key;
int value;
list_item *next;
};
struct list
{
struct list_item *first;
};
int main()
{
list *head;
list *new_node;
head = NULL;
head->first = NULL;
for(int i = 0; i < 10; i++)
{
//allocate memory for new_node
new_node = (list*)malloc(sizeof(list));
new_node->first = (list_item*)malloc(sizeof(list_item));
//adding the values
new_node->first->key = i;
new_node->first->value = 10 + i;
//point new_node to first;
new_node->first->next = head->first;
//point first to new_node;
head->first = new_node->first;
}
//print
list *travel;
travel->first = head->first;
int i = 0;
while(travel != NULL)
{
cout << travel->first->value << endl;
travel->first = travel->first->next;
}
return 0;
}

You are creating 10 lists, I think you might try to do something like this:
#include <iostream>
using namespace std;
struct list_item
{
int key;
int value;
list_item *next;
};
struct list
{
struct list_item *first;
};
int main()
{
//Just one head is needed, you can also create this
// on the stack just write:
//list head;
//head.first = NULL;
list *head = (list*)malloc(sizeof(list));
list_item *new_node = NULL;
head->first = NULL;
for(int i = 0; i < 10; i++)
{
//allocate memory for new_node
new_node = (list_item*)malloc(sizeof(list_item));
//adding the values
new_node->key = i;
new_node->value = 10 + i;
//if the list is empty, the element you are inserting
//doesn't have a next element
new_node->next = head->first;
//point first to new_node. This will result in a LIFO
//(Last in First out) behaviour. You can see that when you
//compile
head->first = new_node;
}
//print the list
list_item *travel;
travel = head->first;
while(travel != NULL)
{
cout << travel->value << endl;
travel = travel->next;
}
//here it doesn't matter, but in general you should also make
//sure to free the elements
return 0;
}
This is what is going on. At first you only have one head and no elements.
head
|
|
V
NULL
Then you add your first element. Make sure that the "new_node->next==NULL":
head
|
|
V
node: ------------------> NULL
key = 0
value = 10
Then you add another node in front but append your first node to its next node. you move the pointer from the head to the new node
head:
first
|
|
V
node: ---------> node: -------------> NULL
key: 1 key: 0
value: 11 value: 10
etc.
Since you are using c++, you might consider using "new" and "delete". Just replace
new_node = (list_item*)malloc(sizeof(list_item));
with
list *head = new list

The next line only allocates memory for your list struct. The list contains only a pointer, you must also allocate memory for new_node->first before assigning to any of its members.
//allocate memory for new_node
new_node = (list*)malloc(sizeof(list));

I think you want something more like this:
#include <iostream>
#include <cstdlib>
using namespace std;
typedef struct tag_list_item
{
int key;
int value;
struct tag_list_item *next;
} list_item;
typedef struct
{
list_item *head;
} list;
int main()
{
list my_list;
list_item *new_node;
list_item *previous_node = NULL;
my_list.head = NULL;
for(int i = 0; i < 10; i++)
{
//allocate memory for new_node
new_node = (list_item*)malloc(sizeof(list_item));
//adding the values
new_node->key = i;
new_node->value = 10 + i;
if(previous_node == NULL)
{
my_list.head = new_node;
}
else
{
previous_node->next = new_node;
}
previous_node = new_node;
}
//print
list_item *iter = my_list.head;
while(iter != NULL)
{
cout << iter->value << endl;
iter = iter->next;
}
return 0;
}
Changes of note:
For malloc, I added:
#include <cstdlib>
I changed your list structures to typedefs, had to declare "next" using the tag since the typedef isn't complete at that point
typedef struct tag_list_item
{
int key;
int value;
struct tag_list_item *next;
} list_item;
I changed your list name to "my_list" and declared it directly (without the pointer). In this case you can just have the compiler allocate it automatically on the stack.
list my_list;
I keep a pointer for "previous_node" so that you can assign the "next" pointer much more easily. Notice that the first node allocated is pointed to by the "head" pointer in the list structure. I believe that is the traditional name for the pointer to the first element in a list.
if(previous_node == NULL)
{
my_list.head = new_node;
}
else
{
previous_node->next = new_node;
}
previous_node = new_node;

head = NULL;
head->first = NULL;
There's the issue. You can't follow a pointer and set it to NULL if you've set the pointer itself to NULL.
That should be
head = malloc(sizeof(list));
head->first = NULL;
That should fix your code.
Hope that helps,
Billy3
EDIT: There's also an issue with your FOR loop. When you allocate the list, you should only allocate the list itself once. When you insert an item, you only allocate a list_item. You're assigning a list pointer to a member which accepts only a list_item pointer ;)
See Gabe's post for a demonstration of correct behavior :)

Look at your struct declaration
struct list_item
{
int key;
int value;
list_item *next;
};
That should be
struct list_item
{
int key;
int value;
struct list_item *next;
};
Hope this helps,
Best regards,
Tom

Related

Error "Abort signal from abort(3) (sigabrt) " for linked list in C++

The following code is for a basic circular linked list, but when one inputs a large value for n(e.g 8 digits) it throws the "abort signal from abort(3) (sigabrt)" error. I'm not sure what it means and would love some guidance about fixing this with regard to my code.
Thank you!
#include<bits/stdc++.h>
using namespace std;
//First I created a structure for a node in a circular linked list
struct Node
{
int data;
struct Node *next;
};
// function to create a new node
Node *newNode(int data)
{
Node *temporary = new Node;
temporary->next = temporary;
temporary->data = data;
return temporary;
}
// This function finds the last man standing in
//the game of elimination
void gameOfElimination(int m, int n)
{
//first I created a circular linked list of the size which the user inputted
Node *head = newNode(1);
Node *prev = head;
//this loop links the previous node to the next node, and so on.
for (int index = 2; index <= n; index++)
{
prev->next = newNode(index);
prev = prev->next;
}
prev->next = head; //This connects the last and first nodes in our linked list together.
//when only one node is left, which is our answer:
Node *ptr1 = head, *ptr2 = head;
while (ptr1->next != ptr1)
{
int count = 1;
while (count != m)
{
ptr2 = ptr1;
ptr1 = ptr1->next;
count++;
}
/* Remove the m-th node */
ptr2->next = ptr1->next;
ptr1 = ptr2->next;
}
printf ("%d\n ",
ptr1->data);
}
//main program which takes in values and calls the function:
int main()
{
int n, p;
cin>>n>>p;
int m=p+1;
gameOfElimination(m, n);
return 0;
}
SIGABRT is generally issued when there are memory issues (heap corruption being quite common). In your code, I see only the new() operator being called, but you aren't deleting any unused nodes from your linked list! Seems like you're exhausting the memory allocated to your process.
You might be running out of memory. Check your ram usage during the execution of your program, that might lead to something.
enter code here
#include<bits/stdc++.h>
using namespace std;
class Node{
public:
int data;
Node *next;
};
void traverse(Node *head)
{
while (head != NULL)
{
/* code */
cout<<head->data<<"->";
head = head->next;
}
cout<<"NULL"
}
int main()
{
Node *head = new Node();
Node *second = new Node();;
Node *third = new Node();;
Node *fourth = new Node();;
head->data = 5;
head->next = second;
//cout<<head->data;
second->data=10;
second->next=third;
third->data = 15;
third->next = fourth;
fourth->data = 20;
fourth->next= NULL;
traverse(head);
return 0;
}```

Circular linked list: Infinite loop

I'm trying to make a circular link list but i'm facing with a problem.
If i run the program with those 2 lines of code above, when i compile and run, it gets an infinite loop of cin if the number of elements is higher than 2. Without them works fine but it isn't anymore a circular linked list. Can you help ?
The problem is right here:
toPush->next = head;
head->pred = toPush;
Full code:
#include <iostream>
using namespace std;
typedef int data;
// Nodes
struct elements {
data value;
elements* next;
elements* pred;
};
// Function that pushes the element to the end
void insertElementEnding(elements* &head, data var) {
elements* toPush = new elements;
toPush->value = var;
toPush->next = NULL;
toPush->pred = NULL;
if(head == NULL) {
head = toPush;
} else {
elements* node = new elements;
node = head;
while(node->next != NULL) {
node = node->next;
}
node->next = toPush;
toPush->pred = node;
toPush->next = head;
head->pred = toPush;
}
}
// Function that prints the list
void showList(elements* head, int numbers) {
for(int i = 0; i < numbers && head != NULL; i++) {
cout << head->value;
head = head->next;
}
}
int main() {
elements* head = NULL;
int var, n;
cout << "Introduce the number of elements: ";
cin >> n;
for(int i = 0; i < n; i++) {
cin >> var;
insertElementEnding(head, var);
}
showList(head, n);
return 0;
}
Thanks in advance.
You need to look for the start of the loop, not NULL, ie
while(node->next != NULL)
should be
while(node->next != head)
As a sidenote, you should use nullptr instead of NULL in C++.
Also you have a memory leak in your program. You dont need to allocate new memory just to get a pointer for iterating your list. This right here is the problem:
elements* node = new elements;
node = head;
A better way would just be
elements* node = head;
First, validation for NULL makes sense only to check if the list is not initialized, before inserting the first element in it.
For all other cases it is redundant as the head should always have previous and following elements for the circle. In case it is just one in the least, it points to itself.
Then if you change the function slightly, it will resolve the problem
void insertElementEnding(elements* &head, data var) {
elements* toPush = new elements;
toPush->value = var;
if(head == NULL) {
head = toPush;
head->next = toPush;
head->pred = toPush;
} else {
// insert the new element before the head
head->pred->next = toPush;
head->pred = toPush;
}
}

Linked Lists Help C++

I am having trouble in C++ putting and displaying array into a linked list. I'm having lots of trouble with linked lists in general
Here is my code. It only displays the first number. (It should display 19 21 17 22 33)
#include <iostream>
using namespace std;
struct node {
int age;
node *next;
};
void display(node *t)
{
node *temp = t;
cout << temp->age << " ";
}
int main()
{
int Age[5] = { 19, 21, 17, 22, 33 };
node* List = new node;
List = NULL;
node* temp2 = List;
while (temp2 != NULL)
{
temp2 = temp2->next;
node* List = new node;
List = NULL;
node* temp2 = List;
}
for (int i = 0; i < 5; i++)
{
temp2 = new node;
temp2 -> age = Age[i];
temp2 -> next = NULL;
if (List == NULL)
List = temp2;
}
display(List);
system("PAUSE");
return 0;
}
Take the following code as an example. Note that you have to delete all created nodes at the end of program to avoid memory leaks.
#include <iostream>
#include <cstddef>
using namespace std;
struct node {
int age;
node* next;
};
void display(node* list) {
while (list != NULL) {
cout << list->age << ' ';
list = list->next;
}
}
node* create(int age) {
node* t = new node;
t->age = age;
t->next = NULL;
return t;
}
void add(node* list, node* t) {
while (list->next != NULL) {
list = list->next;
}
list->next = t;
}
void release(node* list) {
while (list != NULL) {
node* t = list;
list = list->next;
delete t;
}
}
int main() {
int arr[5] = { 19, 21, 17, 22, 33 };
node* list = create(arr[0]);
for (int i = 1; i < 5; i++) {
node* t = create(arr[i]);
add(list, t);
}
display(list);
release(list);
system("PAUSE");
return 0;
}
There's a lot going on here. I'd recommend you look through some tutorials to help solidify your understanding of pointers and linked lists.
To answer your question, let's step through what's happening:
In your main function, you dynamically allocate a node object and have List point to this object. Then, you set List to NULL. When you initialize the node pointer temp2 to List, temp2 also points to NULL.
Because temp2 = NULL, you skip over the following while loop.
In the first iteration of your for loop, you re-assign temp2 to a newly created object, then set the age for that node to the Age[0]. When we get to your if statement, List = NULL so we enter the conditional statement and set List to temp2 where temp2->age = Age[0].
For each additional iteration of your for loop, List no longer is equal to NULL so you never enter your if statement again. List still points to the node where age = Age[0].
When you get to your display function, assuming it was written to loop through a linked list, your List pointer is a list with one node where age = 19. Assuming your had a linked list with multiple valid nodes, your display() function doesn't iterate over them.

How to dynamically create new nodes in linked lists C++

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

Create and Display Linked List

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