I was trying to learn the Linked list and perform insertion operations from beginning of the list. while printing the nodes, the first node is not printed. Here is the core functions which I have written. Can someone help me?
struct Node //basic structure for a node
{
ll data; //data which we want to store
Node* link; //address of the next node;
};
Node* head=NULL;
void Insert(ll x) //insertion at beginning
{
Node* temp=new Node();
temp->data=x;
temp->link=head; //we are linking new node with previously connected node
head=temp;
}
void Print()
{
Node* temp=head;
while(temp->link!=NULL) //traversing the list until last element(last element.link = NULL)
{
cout<<temp->data<<" ";
temp=temp->link;
}
cout<<endl;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
f(i,0,5)
{
ll x;cin>>x;
Insert(x);
}
Print();
return 0;
}
Your Print function requires that the last node is linked or it won't be printed. Since the last node is never linked, it will never be printed.
void Print()
{
Node* temp = head;
while(temp) // <- corrected condition
{
std::cout << temp->data << ' ';
temp = temp->link;
}
std::cout << '\n';
}
It's because of your check in the while. The node will have link set as NULL, and therefore it will exit the while without printing it. My recommendation is changing the while check to (temp != NULL), but you can also fix it by putting a cout << temp->data; after the loop
In general the function Print can invoke undefined behavior when it is called for an empty list due to the expression temp->link that uses a null pointer to access memory.
Another side effect is that the last node will be skipped due to the condition in the while loop (if the list has only one node then its value will not be outputted)
while(temp->link!=NULL)
The function can be declared and defined the following way
std::ostream & Print( std::ostream &os = std::cout )
{
for ( const Node *current = head; current != nullptr; current = current->next )
{
os << current->data << " -> ";
}
return os << "null";
}
And in main the function can be called like
Print() << '\n';
The function is flexible. You can use it to write data in a file providing a corresponding file stream.
The function Insert can be simplified the following way
void Insert( ll x ) //insertion at beginning
{
head = new Node { x, head };
}
Pay attention to that it is a bad idea to declare the pointer head in the global namespace. In this case all functions depend on the global variable and you can not for example to use two lists in your program.
So you should declare the pointer in main.
int main()
{
Node *head = nullptr;
//...
In this case for example the function Insert can look the following way
void Insert( Node * &head, ll x ) //insertion at beginning
{
head = new Node { x, head };
}
and called in main like
Insert( head, x );
Related
I am trying to implement a doubly linked list in C++ and have run across a problem.
#include <iostream>
#include <string>
struct Node
{
std::string data;
Node* prev_link;
Node* next_link;
Node(const std::string& data,Node* prev_link=nullptr, Node* next_link=nullptr)
: data{data},prev_link{prev_link},next_link{next_link} {}// constructor
};
Node* insert(Node* new_node,Node* old_node);// insert node before old node
Node* head(Node* node);// returns a pointer to the head i.e. the left end of the linked list
void print_list(Node* node);//takes the head pointer and executes iterative print
void kill_list(Node* tail_node);// deallocates memory by deleting the list
Node* insert(Node* new_node,Node* old_node)
{
if(new_node == nullptr) return old_node;
if(old_node == nullptr) return new_node;
new_node->next_link = old_node;// p of old node connect to new node
if(old_node->prev_link) old_node->prev_link->next_link = new_node;//n of old' node connect to new node if old' node exists
new_node->prev_link = old_node->prev_link;//p of new node connect to old` node
new_node->next_link = old_node;//n of new node connect to old node
return new_node;
}
Node* head(Node* node)
{
while(node->next_link != nullptr) node = node->next_link;
return node;
}
void print_list(Node* node)
{
while(node)
{
std::cout << node->data;
if(node = node->next_link) std::cout << "<->";// if next node is not an end node
}
}
void kill_list(Node* tail_node)
{
Node* temp;
while (tail_node)
{
temp = (tail_node->prev_link)?tail_node->prev_link:tail_node->next_link;
delete tail_node;
tail_node = temp;
}
std::cout << '\n' <<"List destroyed" << std::endl;
}
int main()
{
Node* alphabets = new Node("A");
alphabets = insert(new Node("B"),alphabets);
alphabets = insert(new Node("C"),alphabets);
print_list(alphabets);
std::cout << '\n';
std::cout << "Head:" << head(alphabets)->data << std::endl;
std::cout << "Adjacent:" << head(alphabets)->prev_link->data << std::endl;
kill_list(alphabets);
}
output:
C<->B<->A
Head:A
fish: “./test1” terminated by signal SIGSEGV (Address boundary error)
The head() function returns a pointer to the head node(in this case it's A).
The linked list as well as the head node is printed correctly but I cannot access the node adjacent to the head node. Cannot figure out what I am doing wrong. Any help would be appreciated.
Your error is because there is a null pointer for the neighbor of A. In your insert function, you have this if statement
if(old_node->prev_link) old_node->prev_link->next_link = new_node
However, in the case of A, there is no prev_link but you would still like to assign B. So replacing that with:
old_node->prev_link = new_node;
fixes the issue. However you might want to double check so that this corresponds to your desired logic.
The problem is due to the fact that the prev_link is not set for the head (the prev link is zero for every node), there is an error on the insert function, you never set the prev_link of the old node.
The below code intends to perform insertion of a single element in a linked list and then print it. Although, I am getting a segmentation fault while printing the value in main function. Could you please help me identify what is wrong with it ?
I have tried to print the value of data in the insert function and it works fine which means the creation of new node and assignment of the value to it is working fine.
#include<iostream>
using namespace std;
struct Node {
int data;
Node* next;
};
//insert a new node
Node* insertNode(int data,Node* head)
{
Node* cNode = head;
if (!head)
{
head = new Node;
head->data = data;
head->next = NULL;
}
else
{
while(cNode->next)
{
cNode = cNode->next;
}
cNode->next = new Node;
cNode->next->data = data;
cNode->next->next = NULL;
}
return head;
}
// print a list
void print(Node* head)
{
/*while(head->next)
{
cout << head->data << " ";
head = head->next;
}*/
cout << "printing data" << endl;
cout << "data : " << head->data;
}
int main()
{
cout << "inside main" << endl;
Node* aNode = NULL;
insertNode(2,aNode);
print(aNode);
return 0;
}
I expect the print function to print the value of data for the single node that I created .
Your head parameter in insertNode function should be a reference (or a pointer to pointer to Node). Beacause in the current form, it is an input parameter, but you need to be in-out parameter. It means that in the current code, your aNode variable is NULL and is always stays NULL.
I recommend this:
void insertNode(int data, Node &head)
Then you create an object in main this way: Node aNode;
It will allow you to update the existing variable directly and you don't need a return value. Also, this way it will be a little bit more C++like, your original code is more like a plain C code.
Or if you want to write it in plain C:
void insertNode(int data, Node **head)
Then you change the call from main: insertNode(2, &aNode);
So hey, I'm having a problem with this project I have. I'm supposed to read integers from a file and insert them into a list. There's a findSpot function that needs to be implemented that traverses the linked list and if the next node's value is larger than what is being checked, it returns the current "spot". And then we output the linked list to a separate file.
Here's the code.
#include <iostream>
#include <fstream>
using namespace std;
class listNode {
public:
int value;
listNode* next;
friend class linkedList;
listNode()
: value(0)
, next(NULL)
{
}
public:
~listNode(){
};
};
class linkedList {
listNode* listHead;
public:
linkedList()
: listHead(NULL)
{
}
bool isEmpty()
{
return (listHead == 0);
}
void listInsert(int data, listNode* spot)
{
listNode* newNode;
newNode->value = data;
newNode->next = NULL;
if (isEmpty()) {
listHead = newNode;
}
else {
newNode->next = spot->next;
spot->next = newNode;
cout << newNode;
}
}
/*void listDelete ()
{
}*/
listNode* findSpot(int data)
{
listNode* spot;
spot = listHead;
while (spot->next != 0 && spot->next->value < data) {
spot = spot->next;
}
return spot;
}
void printList(listNode* spot)
{
listNode* newNode = spot;
while (newNode != NULL) {
cout << "Inserting " << newNode->value << ": "
<< "listHead-->(" << newNode->value << "," << newNode->next->value << ")-->(";
newNode = newNode->next;
}
cout << endl;
}
/*~linkedList()
{
listNode* temp = spot->next;
spot->next = spot->next->next;
delete temp;
}*/
};
int main(int argc, char* argv[])
{
int data;
listNode* spot;
ifstream infile;
infile.open(argv[1]);
ofstream outfile(argv[2]);
cout << "Reading Data from the file" << endl;
while (infile >> data) {
cout << data << endl;
}
infile.close();
linkedList myList;
infile.open(argv[1]);
while (infile >> data) {
myList.findSpot(data);
myList.listInsert(data, spot);
myList.printList(spot);
}
cout << "Printing your linked list to the output file.";
/*while (outfile.is_open())
{
myList.printList();
}*/
infile.close();
outfile.close();
return 0;
}
I don't know if the problem lies mainly in the insertList function or if it's the findSpot function. The findSpot function seems correct to me but I may just be missing something.
As I run the code, the actual reading of the file the first time is fine. Actually inserting anything into the linked list causes the program to hang.
Ok, lets try this again. I'll actually include some code, but please try to use this as a learning point, and not something to just copy paste. I know you said you were copying your teachers algorithm, but what they gave you is probably just that, an algorithm. It is your job to actually implement that in working code, checking for error conditions, etc. Anyway, here we go:
For the function findSpot:
listNode* linkedList::findSpot(int data) {
listNode* spot = listHead; // Initialize spot to start of list
if ( isEmpty() ) // if list is empty, return NULL
return NULL;
// now we know listHead isn't null, so look through the list and
// find the entry that has a value greater than the one provided
// return the list item BEFORE the one with the greater value
while (spot->next != 0 && spot->next->value < data) {
spot = spot->next;
}
// return the one we found; This could be the same as listHead
// (start of list), something in the middle, or the last item on the
// list. If we return from here, it will not be NULL
return spot;
}
Now we can do the insert function:
void linkedList::listInsert(int data, listNode* spot) {
// We need a new item to put on the list, so create it
listNode* newNode = new listNode();
newNode->value = data;
newNode->next = NULL;
// If the list is empty, update the head to point at our new object
if ( isEmpty() ) {
listHead = newNode;
// otherwise point spot to new item, and new item to the one spot
// pointed to
} else {
newNode->next = spot->next;
spot->next = newNode;
}
}
Looking at your print function, that is going to have it's own issues. It looks like you want to print the whole list, but it seems that you are starting to print from "spot". It's all very confused. It also has an issue using newNode->next->value, without checking if newNode->next is NULL. Here's a short example of what I think you are trying to do... note that I don't even need to pass in spot, just the data point added:
void linkedList::printList(int data) {
// if some huckleberry called this before calling insert,
// list will be empty... always a good idea to check
if ( isEmpty())
return;
// first line of output... just print out the data point
// added and start of output text
cout << "Inserted " << data << ": " << "listHead-->(";
// start at start of list
listNode* newNode = listHead;
// loop through until we find the end
while (newNode != NULL) {
cout << newNode->value; // print the value
newNode = newNode->next; // move to the next item on the list
// We moved to the next node; It might be NULL and the loop will end
// if not, we want to print an open bracket since we know another one
// is going to be printed
if ( newNode != NULL )
cout << ")-->(";
}
// last item was just printed, so close off the last bracket
cout << ")" << endl;
}
Hope that is somewhat helpful
Since this looks like a homework assignment, I'm going to give you one fix:
change
myList.findSpot(data);
to
spot = myList.findSpot(data);
If you look closely, spot is used, but never assigned anything.
Well, there are several problems with your program (besides formatting). In the function findSpot(), you have:
listNode* spot;
spot = listHead;
while (spot->next != 0 && spot->next->value < data) {
spot = spot->next;
}
return spot;
The problem here is that the first time you call this, listHead is NULL, so the
while (spot->next
is going to fail, since spot is NULL.
I also notice that nowhere in your code do you call new(). In listInsert, you need to use new() to initialize your newNode variable.
Lastly, find spot has 2 conditions where it can return NULL. If the list is empty, it should return NULL, and you would want to insert at the start of the list. If the new value you are adding is greater than all the others, you will also return NULL and you would have to add to the end of the list.
Since this is a homework assignment, I don't want to write the code for you, but hopefully that helps.
I am currently learning some C++ for a course I am taking in school. I have basic understanding of lvalues and rvalues, but I am unable to determine why I am receiving a compiler error.
I am creating a singly linked list and need to be able to reverse it. As per my assignment I have two classes. The first is the node and just holds an int as well as a pointer.
class Node {
int data;
Node *next;
public:
//Constructor
Node(int d) {
data = d;
next = NULL;}
//Set to next Node
void SetNext(Node *nextOne) {
next = nextOne;}
//Returns data value
int Data(){return data;}
//Returns next Node
Node *Next() {return next;}
};
Then I have a linked list class that has a header pointer and then a number of functions for adding, printing etc. the list.
class LinkedList {
Node *head;
public:
//Constructor
LinkedList(){head = NULL;}
void AddNode(int d) {
//Create a new Node
Node *newNode = new Node(d);
//Create a temporary pointer
Node *temp = head;
//If there are already nodes in the list
if(temp != NULL) {
//Parse through to the end of the list
while(temp->Next() != NULL) {
temp = temp->Next();}
//Point the last Node in the list to the new Node
temp->SetNext(newNode);
}
//If adding as the first Node
else{
head = newNode;}
}
void PrintList() {
//Temporary pointer
Node *temp = head;
//If there are no nodes in the list
if(temp == NULL) {
std::cout << "The list is empty" << std::endl;}
//If there is only one node in the list
if(temp->Next() == NULL) {
std::cout << temp->Data() << std::endl;}
//Parse through the list and print
else {
do {
std::cout << temp->Data();
temp = temp->Next();
}
while(temp != NULL);
}
}
//Returns the number of nodes in the list
int CountList() {
//Temporary pointer
Node *temp = head;
//Counter variable
int counter = 0;
//If the list is empty
if(temp == NULL) {
return counter;}
//Parse through Nodes counting them
else {
do {counter++;
temp = temp->Next();
}
while(temp != NULL);
}
return counter;
}
//Reverses the list
Node *ReverseList() {
//Initially set to NULL then tracks the new head
Node *marker = NULL;
//Tracks the next one in the list
Node *nextOne;
//Sets the first Node to NULL and then sets the last Node to point to
//the first one and rotates through the list pointing the last to the
//first
while(head != NULL) {
nextOne = head->Next();
head->Next() = marker;
marker = head;
head = nextOne;
}
//Setting the head back to the start again
head = marker;
}
};
One of those functions is supposed to reverse the list. The line "head->Next() = marker;" in the ReverseList function is causing a "lvalue required as left operand of assignment" error when compiling.
Any insight as to why this is occurring and how I can correct the problem?
Thank you in advance!
The return from the call to Next() is an rvalue. As you are in a class function, you don't need to call the Next function to get at the private next pointer, you can just use it directly.
head->next = marker;
Your Next() function returns a pointer, and you then do this:
head->Next() = marker;
You're changing the pointer to marker and not what it's pointing at. To solve this you need to dereference that pointer:
*head->Next() = marker;
your signature for next is:
Node *Next() {return next;}
This makes a copy of next pointer at return and hence it is treated as r-value and not l-value.
One way of overcoming this would be to use a pointer-to-pointer:.
Node **Next() {return &next;}
And then use it as:
int main()
{
Node* marker=new Node(89);
Node* nod=new Node(9);
*(nod->Next())= marker;
cout<<(nod->next)->data<<endl;
cout << "Hello World" << endl;
return 0;
}
This makes it more complicated to use.
Here's the reference code:
#include <iostream>
using namespace std;
class linkedList {
struct listNode{ //a node of a list
int value;
struct listNode *next;
};
listNode *head;
public:
linkedList(){
cout << "hello1\n";
head = NULL;
};
linkedList(listNode* a){
cout << "hello2\n";
head = a;
};
~linkedList();
listNode* getHead() {return head;}
void appendNode(int);
//inline Search function due to unable to function outside of class definition
listNode* rangeSearch(int a, int b){
//listNode to search
listNode *search = head;
//listNode* toReturn = new listNode;
//listNode to return list of values that are found within range
linkedList *found = new linkedList;
while(search){
//if the current value is within range, then add to list
if(search->value >= a && search->value <= b){
//append searched value onto found
found->appendNode(search->value);
//after appending, go to next value
}
search = search->next;
}
return found->getHead();
}
void display();
};
int main()
{
cout << "Programmer : n\n";
cout << "Description : \n";
linkedList* list = new linkedList;
int x = 12;
//values to search
int s1 = 10, s2 = 14;
// adds 2 to each number on list for 5 times
for(int i = 0; i < 5; i++){
list->appendNode(x);
x += 2;
}
//create something to hold pointer of found to be deleted when done using
//print list
cout << "Original set of numbers in linked list: ";
list->display();
cout << "\nThe following are the values withing ranges: " << s1 << " and " << s2 << ":\n";
//EDITED:
//list->rangeSearch(s1,s2);
linkedList foundList(list->rangeSearch(s1,s2));
foundList.display();
//End of edit 6:40PM 7/18/13
cout << "\nHere are the original set of numbers in linked list (again): ";
list->display();
delete list;
return 0;
}
void linkedList::appendNode(int newValue)
{
listNode *newNode = new listNode(); // To point to a new node
listNode *nodePtr; // To move through the list
// Allocate a new node and store newValue there.
newNode->value = newValue;
newNode->next = 0;
// If there are no nodes in the list
// make newNode the first node.
if (!head)
head = newNode;
else // Otherwise, insert newNode at end.
{
// Initialize nodePtr to head of list.
nodePtr = head;
// Find the last node in the list.
while (nodePtr->next)
nodePtr = nodePtr->next;
// Insert newNode as the last node.
nodePtr->next = newNode;
}
}
void linkedList::display() {
for(listNode* p = head; p != NULL; p = p->next)
cout << p->value << ' ';
}
linkedList::~linkedList()
{
cout << "\ndestructor called";
listNode *nodePtr; // To traverse the list
listNode *nextNode; // To point to the next node
// Position nodePtr at the head of the list.
nodePtr = head;
// While nodePtr is not at the end of the list...
while (nodePtr != NULL)
{
// Save a pointer to the next node.
nextNode = nodePtr->next;
// Delete the current node.
delete nodePtr;
// Position nodePtr at the next node.
nodePtr = nextNode;
}
}
So a couple of questions here. First, why is it when I try to put the rangeSearch member function outside of the class definition, the compiler gives an error saying listNode* type is not recognized?
Second, this has to do with destructors. In this program, 2 instances (list & found list) were created but only 1 destructor was called. Can someone explain why? My intuition tells me that the dynamically allocated pointer to linkedList object did not get destructed. However, I don't know why. The reason I had to use dynamically allocated memory is primarily because I want to pass the pointer back to the main function. If I don't, when rangeSearch exits, the pointer will be passed back to main but whatever list the pointer had would be deconstructed after
return ptr; (assume ptr is a pointer to a linkedList declared in rangeSearch)
which will cause my program to crash because, now the address has nothing in it and I'm trying to call... nothing.
Well, as usual I would appreciate whoever the great Samaritan out there who would be more than willing to educate me more about this.
First, you are having an issue with scoping. In C++, the curly braces define a new scope, so you are defining listNode inside the class linkedlist. If you want to access it, you'd have to use the scoping operator as such linkedlist::listNode
I don't entirely understand your second question. I only see one call to delete, so why do you think two destructors will be called? The destructors are only called when you call delete, so unless you specify that you want to destroy it, it's still going to be there.
Although I don't entirely understand your question, I see that you returned a pointer to the head in rangeSearch, but you don't assign it to anything. What this means is that you will have a memory leak; you allocated memory for the found, but then don't do anything with it. Actually since you only return the head, you still wouldn't be able to delete it if you did assign something to it, because you wouldn't have access to linked list itself.
linkNode is nested inside of linkedList. Move listNode outside of the linkedList class, and you won't get the first error. Or you can use it's full declaration, linkedList::listNode. Also, if you leave linkNode nested, you will have to make it public.
In main, you can just say
linkedList list;
instead of
linkedList* list = new linkedList;
rangeSearch() is returning a value, but that value is never being assigned to anything in main(). rangeSearch() is allocating a linkedList, but it never gets deleted.