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.
Related
I'm currently working on a class project where we make a linked list and we're supposed to create a function that clears the list then deletes it (with "delete LIST_NAME;"). I have implemented the function as instructed by my professor, also forcing the list to become null after the delete. The function works within itself, but when it returns to the main function, the list gets a new value.
Is this sort of function just not possible in C++?
#include <iostream>
struct Node
{
int val;
Node* next;
};
struct LinkedList
{
int count;
Node* head;
Node* tail;
};
void Clear(LinkedList* list) {
Node* node = list->head;
Node* next = nullptr;
while (node != nullptr) {
next = node->next;
delete node;
node = next;
}
list->head = nullptr;
list->tail = nullptr;
list->count = 0;
}
void Destroy (LinkedList* list) {
Clear(list);
delete list;
list = nullptr;
std::cout << "\n(should be) Destroyed";
}
int main() {
//creating a list element
Node* node = new Node;
node->val = 'a';
node->next = nullptr;
//inserting the element onto list
LinkedList* list = new LinkedList;
list->count = 0;
list->head = node;
list->tail = node;
std::cout << "\nList: " << list;
Destroy(list);
std::cout << "\nList: " << list;
std::cout << "\nEND";
}
This is just a snip of my code but it shows what I mean. Using the debugger the list has the value 0x0 by the end of the function but in the main function it's assigned a new value as shown by the debugger.
You take list by value so it's local to the function.
If you'd like to make changes to it that are visible at the call site, take it by reference:
// `list` is now a reference to the pointer at the call site:
void Destroy(LinkedList*& list) {
Clear(list);
delete list;
list = nullptr; // this now sets the referenced `LinkedList*` to `nullptr`
std::cout << "\n(should be) Destroyed";
}
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 );
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);
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.
I wanted to test the following code (which works fine for a non-null list) to see what would happen in the case of an empty list (in which case the head would be null).
hence the code which applies to filling the list is commented out..
But for some strange reason, the test for NULL in print_nodes() just doesnt seem to work. ive added some debug cout calls to see (and also checked using gdb) but whilst the value does indeed appear to be NULL, any if statements dont seem to test the equivalence properly..
any idea why?
many thanks!
#include <iostream>
using namespace std;
struct node {
char dat;
node *nextPtr;
};
//inserts new node and returns pointer
node* new_node(char data, node* prevNode);
//adds a new node at the head ofthe list
void new_head (node *head_, char dat_);
//inserts new node after *before
void insert_node (node *before, char dat_);
//runs through and prints the list - requires first node (head)
void print_nodes (node *head);
int main() {
cout <<endl << endl;
cout << endl << "*******************RUN******************" <<endl <<endl;
node* head = NULL;
if (head == NULL) {
cout << "head null"; //this works here
}
//head non-standard
// node* head = new node;
// head->dat ='a';
/*
node* b = new_node('b', head);
node* c = new_node('c', b);
node* d = new_node('d', c);
node* e = new_node('e', d);
node* f = new_node('f', e);
*/
print_nodes(head);
insert_node(head,'N');
print_nodes(head);
cout << endl << "*******************END RUN******************" <<endl;
return 0;
}
node* new_node(char data, node* prevNode) {
node* tempPtr = new node;
tempPtr->dat = data;
tempPtr->nextPtr = NULL; //standard
prevNode->nextPtr = tempPtr;
return tempPtr;
}
void new_head (node *head_, char dat_) {
}
void insert_node (node *before, char dat_) {
node* tempPtr = new node;
tempPtr->dat = dat_;
tempPtr->nextPtr = before->nextPtr;
before->nextPtr = tempPtr;
}
void print_nodes (node *head) {
node* tempPtr = head;
cout << "\nPrinting nodes..." <<endl;
if (tempPtr == NULL) { //this test is not working.. why?
cout << "tempPtr is NULL";
return;
} else { //only run in the non null case
for (tempPtr; tempPtr != NULL; tempPtr = tempPtr->nextPtr) {
cout << "Current node content: " << tempPtr->dat <<endl;
}
}
}
You have a problem: head was not allocated, but insert accesses its "next element":
before->nextPtr = tempPtr;
head is passed in as before, and you didn't allocate memory for head. Hence you dereference a NULL pointer here.
Could it be that your application crashes as a result, and the printout to cout isn't done because cout is buffered?
Try to:
Remove the call to insert
Change cout to cerr (unbuffered)
Report the results of these changes.
allocate head before insertion :
node * head = new node;
memset(head, 0, sizeof(node));
The code works for me using g++ 4.4.1 on windows. The message is displayed and then it crashes, because of other issues in the code. You are probably not seeing the message because the crash occurs before the output buffer containing the message is flushed.
In general, it is a good idea to write diagnostic messages to standard error (cerr) rather than standard output, as the error stream is not buffered.