I'm trying to implement insertion sort with link list in C++. But, whenever I'm trying to assign pointer to new node to a link, it gives "segmentation fault (core dumped)". I've checked the line "(*head)->next = newNode;" gives this error.
To run the program compile the program and for input copy the two lines inside comment before the start of insertionSort.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
class Node
{
public:
int num;
Node *prev;
Node *next;
Node(int input);
};
Node::Node(int input)
{
num = input;
prev = NULL;
next = NULL;
}
/*
5 2
1 5 3 4 2
*/
void insertionSort(Node **head, int newInput)
{
Node* newNode = new Node(newInput);
if (*head == NULL)
{
*head = newNode;
}
else
{
Node *itr = *head;
if (itr->num >= newInput)
{
newNode->next = itr->next;
itr->prev = newNode;
*head = itr;
}
else
{
Node *itr = (*head)->next;
while (itr != NULL)
{
if (itr->num >= newInput)
{
newNode->prev = itr->prev;
newNode->next = itr;
itr->prev = newNode;
newNode->prev->next = newNode;
newNode = NULL;
}
itr = itr->next;
}
if (newNode != NULL)
{
if (itr == NULL) {
(*head)->next = newNode;
}
else
itr->next = newNode;
}
}
}
}
void printList(Node *head)
{
Node *itr = head;
while (itr != NULL)
{
cout << itr->num << " ";
itr = itr->next;
}
cout << endl;
}
int main()
{
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int n, k;
cin >> n >> k;
Node *head = NULL;
int num, i = -1;
while (++i < n)
{
cin >> num;
insertionSort(&head, num);
}
printList(head);
return 0;
}
Try changing
itr->prev = newNode;
to
newNode->prev = newNode;
I'm running your code, and get a write access violation. "newNode->prev was nullptr"
You seemed got your variables mixed up in line 53:
newNode->prev->next = newNode;
should be:
its->prev->next = newNode;
And it has to be executed before its->prev is overwritten. But then the code is still not functioning as you want it. You have put some more effort into it. Within the while-loop, you set newNode to NULL and then reiterate.
And you should really comment your code. You understand your own mistakes better when you describe what you are doing.
By the way, did you notice that you mask Node* itr from line 36 at line 45? you could just reuse the existing object, as you don't use it anymore.
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 don't know why PrintList() doesn't terminate. It is a LinkedList, so when I go to next, that should terminate.
When I do AddNode once and then print, that terminates, when I do addNode twice, print doesn't terminate.
The reason why in constructor I create 5 empty spots is because I'm required to create those 5 empty spots when program starts.
Moreover, if for example I add twice , how I can assign pointer to that second value?
#pragma once
class LinkedList
{
private:
typedef struct node {
int data;
node* next;
}* nodePtr;
nodePtr n;
nodePtr head;
nodePtr curr;
nodePtr temp;
public:
LinkedList();
void AddNode(int addData);
void PrintList();
~LinkedList();
};
#include "LinkedList.h"
#include<cstdlib>
#include<iostream>
using namespace std;
LinkedList::LinkedList()
{
head = NULL;
curr = NULL;
temp = NULL;
n = new node;
for (int x = 1; x <= 5; x++) {
//cout << n<<endl;
n->next = n;
}
}
void LinkedList::AddNode(int addData) {
//nodePtr n = new node;
n->next = NULL;
n->data = addData;
cout << n <<endl;
if (head != NULL) {
curr = head;
while (curr->next != NULL) {
curr = curr->next;
}
curr->next = n;
}
else {
head = n;
}
}
void LinkedList::PrintList() {
curr = head;
while (curr != NULL) {
cout << curr->data << endl;
curr = curr->next;
}
}
LinkedList::~LinkedList()
{
head = NULL;
curr = NULL;
temp = NULL;
delete n;
}
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include "LinkedList.h"
using namespace std;
int main() {
LinkedList *l = new LinkedList();
l->AddNode(5);
l->AddNode(8);
l->PrintList();
system("pause");
return 0;
}
The node n is always the same since you are not setting n to a different node
So when you do n->next and n->data , the same node is being modified each time
void LinkedList::AddNode(int addData) {
//nodePtr n = new node; // you need to uncomment this
n->next = NULL;
n->data = addData;
cout << n <<endl;
if (head != NULL) {
curr = head;
while (curr->next != NULL) {
curr = curr->next;
}
curr->next = n;
}
else {
head = n;
}
}
After your first addNode(5), lets examine the values.
head = n
head->data = 5
head->next = null
After your second addNode(8)
head = n
head->data = 8
head->next = n // set by "curr->next = n" .
So you have a problem here. When you try to loop through your linked list, it will become head->next->head->next->head->next->head->next ..... causing an infinite loop
I am trying to read a text file,sort it each user with respect to their number in text file then add it to the linked list.then display it again respect to user number of each node in descending order.also i am trying to add functions to edit like deleting or updating the content.
txt file is like
John Doe ; 10
Sally Tully ; 5
James Watson ; 12
what i have achieved is this:
list.h:
#include<string>
#ifndef LIST_H
#define LIST_H
class list{
private:
struct node{
std::string data;
node* next;
};
typedef struct node* nodePtr;
nodePtr head;
nodePtr curr;
nodePtr temp;
public:
list();
void AddNode(std::string addData);
void DeleteNode(std::string delData);
void PrintList();
};
#endif
list.cpp
#include <cstdlib>
#include <iostream>
#include "list.h"
using namespace std;
list::list(){ //constructor
head = NULL;
curr= NULL;
temp=NULL;
}
void list::AddNode(string addData){
nodePtr n = new node; //nodePtr is node*
n->next=NULL; //find node n is pointing to, access its next element make it point to null
n->data= addData;
if(head != NULL) { // if we have at least 1 element in the list .
curr = head; // take the current pointer we are working with and make it same with head pointer pointing to.(current= front of list)
while(curr->next !=NULL){ // are we at the end of the list.
curr = curr->next;//we are not end of the list.curr pointer points next node.
}
curr->next = n;
}else{ //if we dont have at least 1 element in the list.
head =n;
}
}
void list::DeleteNode(string delData){
nodePtr delPtr = NULL;
temp = head;
curr = head;
while(curr != NULL && curr->data != delData){ // look for data user wants to delete
temp = curr;
curr = curr->next;
}
if(curr == NULL){ // we cant find we are looking for.
cout << delData << "not in list"<<endl;
delete delPtr;
}else{ // we found it
delPtr = curr;
curr = curr->next; // with those 2 lines we are patching the hole in the list.
temp->next = curr;
if(delPtr == head){
head = head->next;
temp = NULL;
}
delete delPtr;
cout<<delData<<"deleted"<<endl;
}
}
void list::PrintList(){
curr = head;
while(curr !=NULL){
cout<<curr->data<<endl;
curr = curr->next;
}
}
int main(){
list mylist;
mylist.AddNode("hello");
mylist.AddNode("how u doin");
mylist.AddNode("good");
mylist.PrintList();
return 0;
}
after reading the txt file should i put them into a vector(or directly to list) then sort then put to linked list ? i guess its wrong i should put them directly then sort before printing on screen. also i dont have any idea how to do updating node by user input function.
update:
I achieved adding content to linked list from txt file.
string file;
ifstream filein;
cout << "Enter file name:"<<endl;
cin >> file;
filein.open(file);
for(;filein.fail();)
{
cout << "Cannot open the file"<<endl;
cout << "Enter file name:"<<endl;
cin >> file;
filein.open(file);
}
string cline;
string cname;
string csurname;
int money;
string smoney;
string lastdata;
char delimiter=';';
while (std::getline(filein, cline)){
std::istringstream iss(cline);
while(iss >> cname >> csurname >> delimiter >> money){
ostringstream temp; // int to string
temp<<money;
smoney=temp.str();
lastdata = cname+" "+csurname+" "+smoney;
mylist.AddNode(lastdata);
}
}
mylist.PrintList();
now it adds like
john doe 10
sally tully 5
the problem is how im gonna reach this 10 and sort them while printing on screen
One way o solve the problem is to create two kinds of methods, one that deals with the comparison and other one that sort the linked list.
The below method deals with comparison. In this case it is comparing the length of the string, but it could be anything.
bool list::IsGreater(nodePtr a, nodePtr b)
{
if (a->data.length() > b->data.length())
return true;
return false;
}
The second method sorts the linked list. Even if there is a sort method, the easiest way is to keep the list sorted during the method AddNode.
void list::SortList() {
for (nodePtr i = head; i != NULL; i = i->next) {
nodePtr prev = NULL;
for (nodePtr j = head; j != NULL && j->next != NULL; j = j->next) {
if (IsGreater(j, j->next)) {
if (prev)
prev->next = j->next;
else
head = j->next;
nodePtr tmp = j->next;
j->next = j->next->next;
tmp->next = j;
j = tmp;
}
if (prev == NULL)
prev = head;
else
prev = j;
}
prev = i;
}
}
I am a newbie to programming
Here I wrote a code for accepting and displaying the values using linked list.
However the code takes all the values but displays only the last value
Here is the code
#include <iostream>
using namespace std;
struct node {
int value;
node* next;
};
class llist {
public:
void create();
void display();
node* head = NULL;
};
void llist::create()
{
struct node* temp;
temp = NULL;
struct node* p;
p = new struct node;
cin >> p->value;
if (head == NULL) {
head = p;
}
else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->value = p->value;
temp->next = NULL;
}
}
void llist::display()
{
struct node* temp = head;
while (temp != NULL) {
cout << "VALUE:" << temp->value << endl;
temp = temp->next;
}
}
int main()
{
int n, i;
llist l1;
cin >> n;
for (i = 0; i < n; i++)
l1.create();
cout << "Displaying list\n";
l1.display();
return 0;
}
Input:
4
1
2
3
4
Displaying list
VALUE:4
I am wondering what went wrong...
Change this:
else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->value = p->value;
temp->next = NULL;
}
to this:
else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = p;
}
When inserting a new element at the end of a linked list, you find the last element inside the while loop and put it in the temp variable. Then you assign its next value to your new p element. The way you were doing before, you were just overriding the integer number of the last element. That is why when you printed your list you only got the last number you entered.
Also, when creating a new element p, be sure to initialize its next value to NULL:
p = new struct node;
p->next = NULL;
Problem is with the last 2 lines in the else block.
You are overwriting the value and maintaining just the single mode in your list class. And that's the reason, only last value is displayed.
Replace
temp->value = p->value;
temp->next = NULL;
With
temp->next = p;
Our homework assignment wanted us to create a "Staque" (implements features of a stack and a queue) using a linked list. When entering even numbers in the list, they should go to the top of the list and odd numbers at the bottom. So if the values inserted are 8 1 4 6 7 9 it should output 6 4 8 1 7 9. Then you delete the top two even numbers and the bottom odd number which would give 8 1 7. Everything seems to work fine except when all the nodes are deleted so when you enter 3 or less values, the program crashes. At this time I have to turn in my assignment since it's due tonight but am just wondering how this can be resolved. Any help would be appreciated.
Here is my code:
Driver:
#include <iostream>
#include "Staq.h"
using namespace std;
int main()
{
Staq *std = new Staq();
int numofvals;
int i;
int x;
cout << "How many values in the staque?" << endl;
cin >> numofvals;
cout << numofvals << " values will be entered in the staque." << endl << endl;;
for(i=1; i<=numofvals; i++)
{
cout << "Enter value " << i << ":" << endl;
cin >> x;
std->AddNode(x);
}
cout << endl;
cout << "Staque:" << endl;
std->PrintList();
std->DeleteNode();
cout << "\nStaque after deletions:" << endl;
std->PrintList();
return 0;
}
.CPP:
#include <iostream>
using namespace std;
#include "Staq.h"
Staq::Staq()
{
head = NULL;
curr = NULL;
temp = NULL;
}
void Staq::AddNode(int addData)
{
nodePtr n = new node;
n->next = NULL;
n->data = addData;
if(addData % 2 == 0)
{
if(head == NULL)
{
head = n;
curr = n;
}
else
{
n->next = head;
head = n;
}
}
else
{
if(head == NULL)
{
head = n;
curr = n;
}
else
{
temp = head;
while(temp->next != NULL)
{
temp = temp->next;
}
temp->next = n;
}
}
}
void Staq::DeleteNode()
{
nodePtr temp2 = new node;
if(head->data %2 == 0)
{
temp = head;
head = head->next;
delete temp;
if(head->data %2 == 0)
{
temp = head;
head = head->next;
delete temp;
}
}
temp = head;
while(temp->next->next != NULL)
{
temp = temp->next;
}
if(temp->data %2 != 0)
{
temp2 = temp->next;
temp->next = NULL;
delete temp2;
}
}
void Staq::PrintList()
{
curr = head;
while(curr != NULL)
{
cout << curr->data << endl;
curr = curr->next;
}
}
Header:
#include <iostream>
using namespace std;
#ifndef STAQ_H
#define STAQ_H
class Staq
{
public:
Staq();
~Staq();
void AddNode(int addData);
void DeleteNode();
void PrintList();
private:
class node
{
public:
int data;
node* next;
};
typedef class node* nodePtr;
nodePtr head;
nodePtr curr;
nodePtr temp;
};
#endif
In DeleteNode, you attempt to access the first node's data, even if there isn't a node. Same goes for the second node.
while(temp->next->next) is dangerous because temp->next could be NULL therefore making temp->next->next an access to null pointer. I assume you meant temp->next. You might want to validate temp too.
Finally, although unrelated, temp2 = temp->next causes a memory leak because now no one points to the new node created at the beginning of DeleteNode.