It looks like in "SortedInsert", the head is always zero and then the code segfaults anyway... really frustrating. Any idea why the head is always zero even though I set it to something, and then why the code segfaults in general?
Thanks
#include <iostream>
#include <cassert>
#include <string>
#include <stdlib.h>
#include <sstream>
using namespace std;
struct Node {
Node* next = 0;
int data;
~Node(){
if (next != 0){
delete next;
}
}
};
void SortedInsert(Node* head, int value){
if(head == 0){
Node* header = new Node;
header->data = value;
head = header;
return;
}
cout << "TEST" << endl;
Node* temp = head;
while(temp != 0){
if(value > temp->data){
Node* insert = temp->next;
Node* otherTemp = new Node;
otherTemp->data = value;
temp->next= otherTemp;
temp->next->next = insert;
}
temp=temp->next;
}
return;
}
int main() {
srand(32);
Node* sortedList = 0;
for (int i = 0; i < 10; i++){
SortedInsert(sortedList, rand() % 100);
}
Node* temp = sortedList;
for (int i=0; i < 9; i++){
assert(temp->data <= temp->next->data);
temp = temp->next;
}
delete sortedList;
}
SortedInsert has its own copy of the head pointer. When you change head inside the function it doesn't affect the value in main. The solution is to pass head by reference or by passing the address.
void SortedInsert(Node** head, int value) {
//Use *head to refer to the head of the list
}
int main() {
...
Node* sortedList = 0;
SortedInsert(&sortedList, ...);
...
}
Or
void SortedInsert(Node*& head, int value) {
//Use head to refer to the head of the list
}
int main() {
...
Node* sortedList = 0;
SortedInsert(sortedList, ...);
...
}
Try the following
void SortedInsert( Node* &head, int value )
{
if ( head == nullptr || value < head->data )
{
head = new Node { head, value };
}
else
{
Node *current = head;
while ( current->next != nullptr && !( value < current->next->data ) )
{
current = current->next;
}
Node *tmp = new Node { current->next, value };
current->next = tmp;
}
}
As for your funcion implementation then the function deals with a copy of the head. Any changes of the copy do not influence on the argument itself. You should pass the head by reference or return the head from the function.
Related
I tried to get output after call insertNodeToEnd and displayNode. Bu I did not get any output. What is problem here?
#include <iostream>
using namespace std;
struct Node{
int data;
Node* next;
};
void displayNode(Node* head ){
while(head!=NULL){//starting pointimiz NULL olana kadar döndür
cout<<head->data<<endl; //NULL olana kadar her Node'un data'sını yazdı
head = head->next;//ilerle
}
}
void insertNodeToEnd(Node*curr , int data){
while(curr->next !=NULL){
curr = curr->next;
}
curr ->next ->data = data;
curr ->next->next = NULL;
}
Node* head; //başlangıc node'unun adresini tuttuk
int main(){
Node* Head = new Node; //bir node oluşturduk
Head -> next = NULL;
Head -> data = 500; //oluşan node'un datasını oluşturduk
Node *iter = Head; //linked list içerisinde dolşacak iterator
//bu iterator'u head olarak tuttuk(artık döngüde iter'i başlangıç olarak kullanacağız)
int i = 0;
for(i = 0 ; i<5 ; i++){
insertNodeToEnd(iter,i*10);
}
displayNode(Head);
}
I tried to get output after call insertNodeToEnd and displayNode. Bu I did not get any output. What is problem here?
The problem is your insertNodeToEnd() is implemented all wrong. It is not creating a new Node, it is accessing curr->next when it is not pointing at a valid node, and it is not taking into account the possibility of head being NULL when the list is empty.
Try something more like this instead:
#include <iostream>
using namespace std;
struct Node{
int data;
Node* next;
};
void displayNodes(Node* head){
while (head != NULL){
cout << head->data << endl;
head = head->next;
}
}
void insertNodeToEnd(Node* &head, int data){
Node *newNode = new Node;
newNode->data = data;
newNode->next = NULL;
if (head == NULL) {
head = newNode;
} else {
Node *curr = head;
while (curr->next != NULL) {
curr = curr->next;
}
curr->next = newNode;
}
}
/* alternatively:
void insertNodeToEnd(Node* &head, int data) {
Node **curr = &head;
while (*curr != NULL) {
curr = &((*curr)->next);
}
*curr = new Node;
(*curr)->data = data;
(*curr)->next = NULL;
}
*/
void freeNodes(Node* head){
while (head != NULL){
Node *next = head->next;
delete head;
head = next;
}
}
int main(){
Node* head = NULL;
insertNodeToEnd(head, 500);
for(int i = 0; i < 5; ++i){
insertNodeToEnd(head, i*10);
}
displayNodes(head);
freeNodes(head);
}
Online Demo
That being said, consider using the standard std::list container instead, eg:
#include <iostream>
#include <list>
using namespace std;
void displayNodes(const list<int> &lst){
for (int elem : lst){
cout << elem << endl;
}
}
int main(){
list<int> lst;
lst.push_back(500);
for(int i = 0; i < 5; ++i){
lst.push_back(i*10);
}
displayNodes(lst);
}
Online Demo
I am really new to data structures. I am trying to figure out why my insertback() function doesn't work. The first print does 3,2,1 but the second doesn't print anything. I think it has something to do with head, but I'm not really sure. Please help.
#include <iostream>
using namespace std;
struct Node
{
int data;
Node* next;
};
class lst
{
public:
void Insertfron(int x);
void Print();
void Insertback(int x);
private:
Node* head;
};
void lst::Insertfron(int x)
{
Node* temp = new Node;
temp->data = x;
temp->next = head;
head = temp;
}
void lst::Print()
{
Node* temp = head;
while(temp->next!=NULL)
{
cout<<temp->data<<' ';
temp=temp->next;
}
cout<< endl;
}
void lst::Insertback(int x)
{
Node* backinst = new Node;
backinst->data = x;
backinst->next = NULL;
Node* temp = head;
while(temp->next!=NULL)
{
temp = temp->next;
}
temp->next = backinst;
}
int main()
{
lst listt;
listt.Insertfron(1);
listt.Insertfron(2);
listt.Insertfron(3);
listt.Print();
listt.Insertback(4);
listt.Print();
return 0;
}
You are not initializing head to NULL to indicate an empty list, so ``head` will have a random garbage value, and thus all of your methods exhibit undefined behavior.
Once that is fixed, your while loops in both Print() and Insertback() are buggy, as they are not account for head being NULL when the list is empty.
Also, you are leaking every node you create. You need to add a destructor to free the nodes when you are done using the list.
With that said, try something more like this instead:
#include <iostream>
using namespace std;
struct Node
{
int data;
Node* next;
};
class lst
{
public:
lst();
~lst();
void Insertfron(int x);
void Print();
void Insertback(int x);
private:
Node* head;
};
lst::lst()
: head(NULL)
{
}
lst::~lst()
{
while (head != NULL)
{
Node *next = head->next;
delete head;
head = next;
}
}
void lst::Insertfron(int x)
{
Node* temp = new Node;
temp->data = x;
temp->next = head;
head = temp;
}
void lst::Print()
{
Node* temp = head;
while (temp != NULL)
{
cout << temp->data << ' ';
temp = temp->next;
}
cout << endl;
}
void lst::Insertback(int x)
{
Node* backinst = new Node;
backinst->data = x;
backinst->next = NULL;
if (head == NULL)
{
head = backinst;
}
else
{
Node* temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = backinst;
}
}
int main()
{
lst listt;
listt.Insertfron(1);
listt.Insertfron(2);
listt.Insertfron(3);
listt.Print();
listt.Insertback(4);
listt.Print();
return 0;
}
That being said, Insertback() can be simplified to avoid the extra if by using an extra level of pointer indirection:
void lst::Insertback(int x)
{
Node **temp = &head;
while (*temp != NULL)
{
temp = &((*temp)->next);
}
Node* backinst = new Node;
backinst->data = x;
backinst->next = NULL;
*temp = backinst;
}
I am facing a problem while coding Linked List implementation in c++. Whenever I am trying to add an element he following code doesn't show any output. What's wrong with the code
#include<iostream>
using namespace std;
struct Node {
int data;
struct Node* ptr;
Node(int val) {
data = val;
ptr = NULL;
}
};
void addItem(struct Node* head, int val) {
struct Node* n = new Node(val);
if(head == NULL){
head = n;
return;
}
struct Node* cur = head;
while(cur->ptr != NULL){
cur = cur->ptr;
}
cur->ptr = n;
}
void printList(struct Node* head) {
struct Node* cur = head;
while(cur != NULL) {
cout << cur->data << " ";
cur = cur->ptr;
}
}
int main() {
struct Node* head = NULL;
addItem(head, 1);
addItem(head, 2);
addItem(head, 3);
addItem(head, 4);
printList(head);
return 0;
}
When I run the program it shows nothing on the terminal.
Output:
[Running] cd "c:\Users\Sonu\" && g++ LinkedList.cpp -o LinkedList && "c:\Users\Sonu\"LinkedList
[Done] exited with code=0 in 3.436 seconds
You should pass head by double pointer or by reference. Otherwise it will be just a copy on function argument which will get destroyed when coming out of the function.
void addItem(Node** head, int val) {
Node* n = new Node(val);
if(*head == NULL){
*head = n;
return;
}
Node* cur = *head;
while(cur->ptr != NULL){
cur = cur->ptr;
}
cur->ptr = n;
}
// ...
addItem(&head, 1); // take the address with &
or
void addItem(Node*& head, int val) {
Node* n = new Node(val);
if(head == NULL){
head = n;
return;
}
Node* cur = head;
while(cur->ptr != NULL){
cur = cur->ptr;
}
cur->ptr = n;
}
// ...
addItem(head, 1); // no change needed
I need to define a class of linked list,List, in a way such that object of class can be defined in two ways,
List obj1 = L1();//head=0
List obj2 = L2(given_arr[], size of array) // I would be given an array, whose elements are elements of list
so, I need to form a construter for both,
for obj1, Its easy.
List(){head=0};
But I am not abe to do so for second type of object.
I tried to form a program for this.
#include <iostream>
using namespace std;
class List {
class node {
public:
int val;
node* next;
};
public:
node* head;
int arr[];
List() { head = 0; }
List(int arr[], int size);
void addnode(int value) {
node* newnode = new node();
newnode->val = value;
newnode->next = NULL;
if (head == NULL) {
head = newnode;
} else {
node* temp = head; // head is not NULL
while (temp->next != NULL) {
temp = temp->next; // go to end of list
}
temp->next = newnode; // linking to newnode
}
}
void display() {
if (head == NULL) {
cout << "List is empty!" << endl;
} else {
node* temp = head;
while (temp != NULL) {
cout << temp->val << " ";
temp = temp->next;
}
cout << endl;
}
}
};
List::List(int arr[], int size) {
int i;
head->val = arr[0];
for (i = 0; i < size; i++) addnode(arr[i]);
}
int main() {
int barr[4] = {9, 89, 0, 43};
List* M = new List();
List* L = new List(barr[4], 4);
L->display();
return 0;
}
This program doesn't work. Please suggest a way to do so.
Make these changes to your main().
int main() {
int barr[] = {9, 89, 0, 43}; // No need to specify size if you're initializing
// List* M = new List(); // unused
// Your array is barr, barr[4] makes no sense. You also don't allocate the List,
// the list allocates
List L = List(barr, sizeof(barr) / sizeof(barr[0]);
L.display(); // -> to .
return 0;
}
This now compiles, but immediately segfaults. Simply running the program in the debugger shows a simple error. The line head->val = arr[0]; attempts to dereference a null pointer. Which takes us to the next thing. Use nullptr, not NULL or 0.
Your array constructor was over-complicated, you just need this:
List::List(int arr[], int size) {
for (int i = 0; i < size; i++) addnode(arr[i]);
}
Your addnode() function already handled an empty list. Fixing that, your code should run. I made a couple other small changes, mostly trimming cruft out. Here's your complete code:
#include <iostream>
using namespace std;
class List {
class node {
public:
int val;
node* next;
};
public:
node* head = nullptr;
List() = default;
List(int arr[], int size);
void addnode(int value) {
node* newnode = new node();
newnode->val = value;
newnode->next = NULL;
if (head == NULL) {
head = newnode;
} else {
node* temp = head; // head is not NULL
while (temp->next != NULL) {
temp = temp->next; // go to end of list
}
temp->next = newnode; // linking to newnode
}
}
void display() {
if (head == NULL) {
cout << "List is empty!" << endl;
} else {
node* temp = head;
while (temp != NULL) {
cout << temp->val << " ";
temp = temp->next;
}
cout << endl;
}
}
};
List::List(int arr[], int size) {
for (int i = 0; i < size; i++) addnode(arr[i]);
}
int main() {
int barr[] = {9, 89, 0, 43};
List L = List(barr, sizeof(barr) / sizeof(barr[0]));
L.display();
return 0;
}
#include <iostream>
using namespace std;
class List {
public:
struct node {
int data;
node *next;
};
node* head = NULL;
node* tail = NULL;
node* temp = NULL;
node* prev = NULL;
public:
void addNum(int num) {
temp = new node;
temp->data = num;
temp->next = NULL;
if (head == NULL) {
head = temp;
tail = temp;
}
else {
tail->next = temp;
tail = temp;
}
}
void PrintList() {
temp = head;
while (temp != NULL) {
cout << temp->data << endl;
temp = temp->next;
}
}
void DelNum(int num) {
temp = head;
while (temp != NULL) {
if (temp->data == num) {
prev->next = temp->next;
free(temp);
}
temp = prev;
temp = temp->next;
}
}
};
int main() {
List list;
list.addNum(1);
list.addNum(2);
list.addNum(3);
list.addNum(4);
list.addNum(5);
list.addNum(6);
list.DelNum(3);
list.PrintList();
return 0;
}
What is wrong with my DelNum function? When I run the program nothing pops up. Doesn't matter what number I put in.
As mss pointed out the problem is in your DelNum() function where you assign temp = prev;. In your initialization you defined that node* prev = NULL; So, prev = NULL at the point when you assigned it to temp which caused segmentation fault when you try to use it like temp = temp->next;.
Two main problems are there in DelNum function:
first, when you are in while loop
, you should assign
prev = temp;
second, when you have found your target element, after deleting it you have to break out of the loop, which isn't done in your code
below is your corrected code( also correction of some other corner case in DelNum function ):
#include <iostream>
using namespace std;
class List {
public:
struct node {
int data;
node *next;
};
node* head = NULL;
node* tail = NULL;
node* temp = NULL;
node* prev = NULL;
public:
void addNum(int num) {
temp = new node;
temp->data = num;
temp->next = NULL;
if (head == NULL) {
head = temp;
tail = temp;
}
else {
tail->next = temp;
tail = temp;
}
cout<<num<<" is added \n";
}
void PrintList() {
temp = head;
while (temp != NULL) {
cout << temp->data << endl;
temp = temp->next;
}
}
void DelNum(int num) {
if(head==NULL)//empty
{
cout<<"empty linked list, can't be deleted\n";
return;
}
if(head->next==NULL)//means only one element is left
{
if(head->data==num)
{
node * fordelete=head;
head=NULL;
cout<<num<<"is deleted\n";
delete(fordelete);
}
else
{
cout<<"not found , can't be deleted\n";
}
return;
}
temp = head; // when more than one element are there
prev = temp;
while (temp != NULL) {
if (temp->data == num) {
prev->next = temp->next;
free(temp);
cout<<num<<" is deleted\n";
break;
}
prev= temp;
temp = temp->next;
}
if(temp==NULL)
{
cout<<"not found, can't be deleted\n";
}
}
};
int main() {
List list;
list.addNum(1);
list.addNum(2);
list.addNum(3);
list.addNum(4);
list.addNum(5);
list.addNum(6);
list.PrintList();
list.DelNum(3);
list.DelNum(7);
list.PrintList();
return 0;
}
I hope it will help you.