C++ linked list , stack ( sort of ) - c++

#include <iostream>
using namespace std;
struct Node
{
int item; // storage for the node's item
Node* next; // pointer to the next node
};
/**************
use reference
**************/
void addNode(Node*& head, int data , int& count)
{
Node * q; // new node
q = new Node; // allocate memory for the new mode
q->item = data; // inserting data for the new node
q->next = head; // point to previous node ?? how would i do that? ( am i doing it correctly?)
count++; // keep track of number of node
head = q;
}
int main()
{
int a, count = 0;
int data;
char callen;
Node *head = NULL;
do
{
cout << "please enter the data for the next node" << endl;
cin >> data;
addNode(head, data, count);
cout << "do you wish to enter another node? (enter true or false)" << endl;
cin >> callen;
}while( callen != 'n' );
// assuming this is the print function
while(head != NULL)
{
cout << "output" << head->item << endl;
head = head->next; //next element
}
system("pause");
return 0;
}
I tried adding a new element in the list how would i move the head around like a LIFO memory (stack) so the last element is on the very top..
Any help would be appreciated ! The pointers and the nodes are messing with my brain lately ....

In the do-while loop try this
addNode(data, count, head);
instead of
addNode( data, count );
Also, change the signature of addNode as follows:
void addNode( int data , int& count , Node*& head)

The code shouldn't compile because you are using the variable head in addNode but head is local to main.

You could use std::stack for LIFO.
int main()
{
int a, count=0;
int data;
bool repeat;
stl::stack<int> lifo;
// assuming it is an empty list at the beginning and crating a new node below
cout << "enter some data" << endl;
cin >> a ;
lifo.push(a);
do
{
cout << "please enter the data for the next node" <<endl;
cin >> data;
lifo.push(data);
cout << "do you wish to enter another node? (enter true or false)" << endl;
cin >> repeat;
}
while (repeat == true);
// assuming this is the print function
while(!lifo.empty()) {
cout << lifo.pop() << endl;
}
system("pause");
return 0;
}

Sounds like you're trying to learn a bit about link lists. Awesome!
Anyway, I'm not going to give you the exact answer, but I'll give you some pointers in pseudo code, in particular for your addNode member function:
Node* addNode(Node* head, int data, int& count)
{
create a new node
let it point to head
return the pointer to the new node for it to become the new head node
}
int main()
{
// code...
head = addNode(head, data, count);
// more code...
}
As a visual:
head
\/
node A->node B->node C
new node->?
new node
\/
node A->node B->node C

The way you're doing it, by implementing your addNode function as a push operation, already moves the head around, so the head will always point to the last element you added.
Therefore, to implement a function to delete the last element added, you just need to write a simple pop operation: copy the address of the head, make the second element the new head, and release the memory at the copied address:
Node* oldHead = head;
head = head->next;
delete oldHead;
return head;

You could try the following modified code.
#include <iostream>
using namespace std;
struct Node
{
int item; // storage for the node's item
Node* next; // pointer to the next node
};
/**************
use reference
**************/
void addNode(Node*& head, int data , int& count)
{
Node * q; // new node
q = new Node; // allocate memory for the new mode
q->item = data; // inserting data for the new node
q->next = head; // point to previous node ?? how would i do that? ( am i doing it correctly?)
count++; // keep track of number of node
head = q;
}
int main()
{
int a, count = 0;
int data;
bool repeat;
Node *head = NULL;
// assuming it is an empty list at the beginning and crating a new node below
Node *temp;
temp = new Node ;
cout << "enter some data" << endl;
cin >> a ;
temp->item = a;
temp->next = head;
head = temp;
//^^ assuming thats creating the first node ^^
do
{
cout << "please enter the data for the next node" << endl;
cin >> data;
addNode(head, data, count);
cout << "do you wish to enter another node? (enter true or false)" << endl;
cin >> repeat;
}
while (repeat == true);
// assuming this is the print function
temp = head;
while(temp != NULL)
{
cout << "output" << temp->item << endl;
temp = temp->next; //next element
}
return 0;
}

Related

display list is only displaying the head of the node

I wrote a code that asks the user to enter a custom list, and I want to display it, but it's only displaying the head node.
I want to know if the problem is from the display function or the input function. I want to remove the display function later, but I want my list to be created.
Here is my code:
#pragma once
#include <cstddef>
#include <iostream>
using namespace std;
struct node {
char data;
node* next;
};
node* inputList();
void displayList(node*);
int exercice1() {
node* head;
head = inputList();
displayList(head);
return 0;
}
node* inputList() {
node* tmp;
node* cur, *head;
int n;
do {
cout << "enter the number of nodes: ";
cin >> n;
} while (n <= 0);
tmp = new node;
cout << "enter the values inside each node: ";
cin >> tmp->data;
head = tmp;
cur = tmp;
for (int i = 1; i < n; i++) {
tmp = new node;
cur = cur->next;
cout << "enter a node: ";
cin >> tmp->data;
cur = tmp;
}
cur->next = NULL;
return head;
}
void displayList(node* head) {
if (head != NULL) {
cout << head->data;
displayList(head->next);
}
}
inputList fails to link the nodes together. We could probably get away with something like
tmp = new node;
cur->next = tmp; // point current node's next at new node
cur = cur->next;
but here's a cleaner approach:
node* inputList() {
node * head; // storage for the start of the list. Keeps track so we
// know what to return when we're done.
node ** insert = &head; // store where we're going to insert a node rather than
// tracking the current node with another variable.
// this is both tmp and cur by always pointing at where
// the next node is going to go.
int n;
do {
cout << "enter the number of nodes: ";
cin >> n;
} while (n <= 0);
*insert = new node; //node goes right into head
cout << "enter the values inside each node: ";
cin >> (*insert)->data;
insert = &(*insert)->next; // now the insertion point points at head's next
for (int i = 1; i < n; i++) {
*insert = new node; // new node gets linked right in next
cout << "enter a node: ";
cin >> (*insert)->data;
insert = &(*insert)->next; // advance to next of the node we just added
}
*insert = NULL; // terminate list by pointing the insertion point at NULL
return head;
}
And now that he have abstracted head into just another insertion point like next, we can eliminate some duplicated code:
node* inputList() {
node * head;
node ** insert = &head; // head is no different from a next. It just
// has a different name
int n;
do {
cout << "enter the number of nodes: ";
cin >> n;
} while (n <= 0);
// no special handling for head.
for (int i = 0; i < n; i++) { // iteration now starts at 0. The loop
// builds all of the nodes.
*insert = new node;
cout << "enter a node: ";
cin >> (*insert)->data;
insert = &(*insert)->next;
}
*insert = NULL;
return head;
}

Struggling to get this push_back() function to work

I'm working on an assignment for my college class, and I'm struggling to figure out why code for my push_front() function works without fail, but my push_back() always gives:
"Exception thrown: read access violation. st was nullptr."
struct NodeDate
{
int day, month, year; //Structure's data
struct NodeDate* nextNode; //Pointer to point to next node
}*start; //Not sure why we do this, but all examples contain it
class LinkedListDate
{
public:
//Prototype of member functions
NodeDate* create_node(NodeDate);
void push_front();
void pop_front();
void remove_front();
void search();
void display();
LinkedListDate();
void push_back();
void remove_back();
void pop_back();
};
LinkedListDate::LinkedListDate()
{
start = NULL; //Our first created pointer will be set to NULL
}
NodeDate* LinkedListDate::create_node(struct NodeDate newDate) //Function that creates a new node and returns said node
{
struct NodeDate* tempNode, *s;
tempNode = new(struct NodeDate); //Reserving memory for our temp node
if (tempNode == NULL) //If the node is empty
{
std::cout << "Memory not allocated " << std::endl;
return 0;
}
else //Otherwise assign parameter node value to temporary node
{
tempNode->day = newDate.day;
tempNode->month = newDate.month;
tempNode->year = newDate.year;
tempNode->nextNode = NULL; //Remember these are all values contained within the date struct
return tempNode; //Return the node
}
}
void LinkedListDate::push_front() //Function that will insert a node at the start of our linkedlist
{
struct NodeDate* tempNode, *st, newNode;
std::cout << "Enter the day: ";
std::cin >> newNode.day;
std::cout << "Enter the month: ";
std::cin >> newNode.month;
std::cout << "Enter the year: ";
std::cin >> newNode.year;
tempNode = create_node(newNode); //Creating a new node for date with the create_node function
if (start == NULL) //Checks if the starting (Head) node is NULL then first node to insert
{
start = tempNode; //Start node points to our temporary node
start->nextNode = NULL; //Assign null to start->next
}
else //Otherwise nodes are already available in the list
{
st = start; //Assign start to st
start = tempNode; //Start points to temporary node
start->nextNode = st; //Start next point to st
}
std::cout << "Element Inserted at beginning" << std::endl;
}
void LinkedListDate::push_back() //Function to insert a new node at the end of the linkedlist
{
struct NodeDate* tempNode, *st, newNode;
std::cout << "Enter the day: ";
std::cin >> newNode.day;
std::cout << "Enter the month: ";
std::cin >> newNode.month;
std::cout << "Enter the year: ";
std::cin >> newNode.year;
tempNode = create_node(newNode); //Creating a new node for date with the create_node function
st = start;
while (st->nextNode != NULL) //Move til we reach end of the list
{
st = st->nextNode; //Move to the next node
}
tempNode->nextNode = NULL; //Assign null to temporary node next
st->nextNode = tempNode; //st next points to temporary node
std::cout << "Element Inserted at last" << std::endl;
}
Again, push_front() works, but push_back() does not work (The program runs, but after inputting the date for the first node I get the exception.
I've been trying a lot of things, but I can't seem to figure out what exactly I'm doing wrong.
struct NodeDate
{
//...
}*start;
is the same is
struct NodeDate
{
//...
};
NodeDate *start;
push_back will fail when the list is empty (i.e. start is null).
void LinkedListDate::push_back()
{
//...
tempNode = create_node(newNode);
tempNode->nextNode = nullptr;
if(start == nullptr)
{
start = tempNode;
}
else
{
st = start;
while (st->nextNode != nullptr) //Move til we reach end of the list
{
st = st->nextNode; //Move to the next node
}
st->nextNode = tempNode;
}
std::cout << "Element Inserted at last" << std::endl;
}

Seg Fault and Pointer issues

Been working on this program for a couple of days in class and I keep getting seg faults. I can comment out the part of code that I think is causing it and I stop getting the fault but then my print function doesn't work. I am picking up the c++ book tomorrow to help.
//linkedList.cpp
//Declaration of main and menu functions
//Programmer: Ronnie Warden
//Date: 2.15.15
#include<iostream>
#include "link.h"
using namespace std;
int main()
{
Node *list = new Node;
int delNode;
int findNode;
int choice = 1;
list->next = NULL;
while (choice != 5)
{
choice = menu();
if (choice == 1)
*list = insertNode(list);
if (choice == 2)
{
cout << "Enter the ID you wish to delete: ";
cin >> delNode;
*list = deleteNode(list, delNode);
}
if (choice == 3)
printNode(list);
if (choice == 4)
{
cout << "Enter the ID you are searching for: ";
cin >> findNode;
*list = searchNode(list, findNode);
}
if (choice < 1 || choice > 5)
cout << "Invalid choice! Please try again." << endl;
}
return 0;
}
int menu()
{
int choice = 1;
cout << "1. Insert Node" << endl;
cout << "2. Delete Node" << endl;
cout << "3. Print List" << endl;
cout << "4. Search List" << endl;
cout << "5. Quit" << endl;
cin >> choice;
return choice;
}
This following part is the one throwing the seg fault.
//linkFun.cpp
//Declaration of functions used to manage the linked list
//Programmer: Ronnie Warden
//Date: 2.10.15
#include<iostream>
#include "link.h"
using namespace std;
/*************************************************************************************************************
Function: createNode
Parameters: No parameters
Return Type: Pointer to new node
Task: Create a node with "new" operator. Get a student data from keyboard and assign to members of the node.
*************************************************************************************************************/
Node createNode()
{
Node *newNode = new Node;
cout << "Last Name?" << endl;
cin >> newNode->lastName;
cout << "First Name?" << endl;
cin >> newNode->firstName;
cout << "ID?" << endl;
cin >> newNode->idNumber;
return *newNode;
}
/**************************************************************************************************************
Function: insertNode
Parameters: Pointer to the linked list
Return Type: Pointer to the linked list
Task: insert a new node to the linked list sorted by student's ID number. If ID is already in list notify user
***************************************************************************************************************/
Node insertNode(Node *list)
{
Node *newNode = new Node;
Node *tmp = new Node;
*newNode = createNode();
int id = newNode->idNumber;
if (list == NULL) //Insert in empty list
list->next = newNode;
else
{
*tmp = searchNode(list, id);
if (tmp->idNumber == newNode->idNumber)
{
cout << "ID number already in list! Please try again with a different ID number." << endl;
insertNode(list);
}
if (list != NULL)
{
Node *tmp = list;
if (tmp->idNumber > newNode->idNumber) //Insert as first
{
newNode->next = tmp;
list = newNode;
}
while (tmp->idNumber < newNode->idNumber) //Search for insertion point
{
if (tmp->next == NULL) //Insert at end
tmp->next == newNode;
tmp = tmp->next;
if (tmp->idNumber < newNode->idNumber && tmp->next->idNumber > newNode->idNumber && tmp->next != NULL) //Insert in-between
{
newNode->next = tmp->next->next;
tmp->next = newNode;
}
}
}
}
return *list;
}
/***************************************************************************************************************
Function: searchNode
Parameters: Pointer to the linked list, student ID number
Return Type: Pointer to the node with matched ID number
Task: Search the linked list by student Id number. Notify user if ID is not found
***************************************************************************************************************/
Node searchNode(Node *list, int id)
{
Node *missing = new Node;
if (list->idNumber == id) //Checks if first node matches id number
return *list;
else
{
Node *tmp = new Node; //creates temporary pointer to scroll through list
while (tmp->idNumber != id)
{
if (tmp->next == NULL) //checks if number is missing returns sentinel if not found
{
missing->idNumber = 9999;
return *missing;
}
tmp = tmp->next;
}
return *tmp;
}
}
/***************************************************************************************************************
Function: deleteNode
Parameters: Pointer to the linked list, student ID number
Return Type: Pointer to the list
Task: Delete a node from the list. Notify user if no node matches
***************************************************************************************************************/
Node deleteNode(Node *list, int id)
{
Node *tmp = new Node;
*tmp = searchNode(list, id);
return *list;
}
/***************************************************************************************************************
Function: printNode
Parameters: Pointer to the linked list
Return Type: None
Task: Display the linked list
***************************************************************************************************************/
void printNode(Node *list)
{
Node *tmp = new Node;
tmp = list;
while (tmp != NULL)
{
cout << tmp->lastName << endl;
cout << tmp->firstName << endl;
cout << tmp->idNumber << endl;
tmp = tmp->next;
}
}
If I comment out the entire else statement in the insertNode function I stop getting the seg fault but then when I call to print it prints 3 blank lines and then 0. Any help would be appreciated, and if it comes up, the reason I didnt use classes was because I am not allowed to, it has to be done in structured data type.
#ifndef LINK_H
#define LINK_H
struct Node {
char lastName[20];
char firstName[20];
int idNumber;
Node *next;
};
int menu();
Node createNode();
Node insertNode(Node*);
Node searchNode(Node*, int);
Node deleteNode(Node*, int);
void printNode(Node*);
#endif
Your main problem is that you're not using pointers right - you're kind of half way between pointers and objects. (I'm not going to address the fact that this is a C style program in C++)
For example: Your createNode() method returns a Node object. It does this by creating a new Node on the heap and then returning that node's contents. This means that you've actually got a memory leak. No one has remembered the pointer to the node you put in the heap and so it leaks.
My first step would be to make createNode() return a Node*
Node* createNode()
{
Node *newNode = new Node;
// All your cout/cin stuff
return newNode;
}
I'd follow the same pattern with the other methods - use pointers rather than objects. Take searchNode() as an example. Because you're using objects, you need a special "Not Found" node. If you use pointers, you can return NULL (preferable 0 in C++) for the "not found case". You also don't need to new and temporary variables.
Node* searchNode(Node* list, int id)
{
while(list != 0) {
if (list->id == id) {
return list;
}
// This only impacts the local list. It doesn't
// permanently change the value of the list
// passed in.
list = list->next;
}
return 0;
}
For bonus points on searchNode(): Since it is a sorted list, you can stop searching as soon as you find an id that is greater than the one you are looking for.
Now that you've done that, your insert method is a bit simpler:
Get a new node from the user
Check if it exists - if so delete the node you just created and give error
If not, search the list and find where to insert your new node.

The program does not give the desired output . Wrong implementation of FIFO ?

This is a FIFO program using linked list . The program does not give the desired output but generates a long loop which stops after sometime and there is a message that the program has stopped working. What is the problem ?
#include <iostream>
using namespace std;
struct node {
int data;
struct node* previous; // This pointer keeps track of the address of the previous node
};
struct queue {
node* first;
node* last;
};
node* dataNode_P_A;
bool loop = true;
struct node* enterData();
struct node* enter_N_Data();
void displayQueue();
int main() {
struct node* dataNode= enterData();
while( loop ) {
cout << "Want to enqueue ? Press y/n : ";
char ans;
cin >> ans;
if( ans == 'y' ) {
struct node* dataNode_N = enter_N_Data();
} else {
break;
}
}
displayQueue();
}
struct node* enterData() {
cout << "Enter the number : ";
dataNode_P_A = new node; // Now dataNode points to a chunk allocated to node
cin >> dataNode_P_A->data;
dataNode_P_A->previous = NULL; // this is set to NULL because no one follows till now
queue* q = new queue;
q->first = dataNode_P_A; // this pointer points to the first element
return dataNode_P_A;
}
struct node* enter_N_Data() {
cout << endl << "Enter the number : ";
node* dataNode = new node;
cin >> dataNode->data;
dataNode->previous = dataNode_P_A;
queue* q = new queue;
q->last = dataNode; // this pointer points to the last element
return dataNode;
}
void displayQueue() {
while( dataNode_P_A != NULL ) {
cout << dataNode_P_A->data << endl;
dataNode_P_A++;
}
}
You are constructing queues and then abandoning them.
You fail to update dataNode_P_A, so that you are not constructing a list so much as a tassel.
You invoke dataNode_P_A++ when you clearly don't know what it means.
You have written a long, complicated piece of code without testing it along the way.
You should start over, and go step by step.
Where to begin... First off the queue data structure isn't particularly used for anything. But that's not the root of your problem. That lies here:
void displayQueue() {
while( dataNode_P_A != NULL ) {
cout << dataNode_P_A->data << endl;
dataNode_P_A++;
}
}
When iterating through a linked list, you move to the next element by navigating to ->previous:
void displayQueue() {
while( dataNode_P_A != NULL ) {
cout << dataNode_P_A->data << endl;
dataNode_P_A = dataNode_P_A->previous;
}
}
Having said that, you're doing some other things that are questionable - like modifying your global list (dataNode_P_A). That's not a problem in your example, but it can be a problem if you ever want to do anything to the list other than display it.
Here's another version of displayQueue that doesn't have that problem:
void displayQueue() {
node *entry = dataNode_P_A;
while( entry != NULL ) {
cout << entry->data << endl;
entry = entry->previous;
}
}
You should edit your enter_N_Data() function like:
node* temp; // global as others in your program
struct node* enter_N_Data() {
cout << endl << "Enter the number : ";
node* dataNode = new node;
cin >> dataNode->data;
temp = new node;
temp = dataNode_P_A;
dataNode_P_A = dataNode; // update dataNode_P_A
dataNode->previous = temp;
queue* q = new queue;
q->last = dataNode; // this pointer points to the last element
return dataNode;
}
and keep everything same while following the suggestions by # Larry Osterman and # Beta.

Inserting an integer at the end of the list and deleting at nth position

So, in my linked list program, what I want it to do is to ask the user how many numbers to input, and enter the numbers, and add those numbers at the end of the list. Then, it will print the list. After that, the user will choose a position of element in the list to delete and the list will be printed again.
#include <iostream>
using namespace std;
struct Node{
int data;
Node* link;
};
Node* head;
void Insert(int data){ //insert an integer at the end of the list
Node* temp = new Node();
Node* temp2 = new Node();
temp->data = data;
temp->link = NULL;
if(head = NULL){
head = temp;
return;
}
temp2 = head;
while(temp2->link != NULL){
temp2 = temp2->link;
}
temp2->link = temp;
}
void Delete(int n){ //delete an integer at nth position
Node* temp1 = new Node();
temp1 = head;
if(n == 1){ //if the first node is to be deleted
head = temp1->link; //now head points to second node
delete temp1; //delete first node
return;
}
for(int i = 0; i < n-2; i++){
temp1 = temp1->link; //temp1 points to (n-1)th node
}
Node* temp2 = temp1->link; //temp2 points to nth node
temp1->link = temp2->link; // pointing to (n+1)th node
delete temp2; //deleting nth node
}
void Print(){ //print out the list
Node* printNode = head;
cout << "List: ";
while(printNode != NULL){
cout << printNode->data;
cout << " ";
printNode = printNode->link;
}
cout << "\n";
}
int main(){
int x, count, n;
head = NULL; //start with an empty list
cout << "How many numbers? " << endl;
cin >> count;
for(int i = 0; i < count; i++){
cout << "Enter number: ";
cin >> x;
Insert(x);
}
Print();
cout << "Enter position to delete: ";
cin >> n;
Delete(n);
Print();
return 0;
}
After accepting the first number, the program stops working. Can I know where I did the code wrong and what can I do to make this code more efficient? Thanks in advance.
Big facepalm on my part, only a small mistake. Code has been corrected.
if(head == NULL){
head = temp;
return;
}
You might need to rethink your insertion function. The part that your code crashes on is during the while loop insertion. If you want temp2 to hold data then you need to dynamically allocate space for it which you did. However, you are just using it as a position indicator (to traverse the list) - so why do you need to allocate space just to point to head or any other nodes location in your list?
Here's how I would insert into the list (at the back of course):
void Insert(int data){ //insert an integer at the end of the list
Node* temp = new Node();
// This is to ensure that temp was created -> Also called defensive programming.
if (!temp)
{
cout << "We did not have enough space alloted to dynamically allocate a node!" << endl;
exit(1);
}
temp->data = data; // Bad nominclature for program; Don't use the same name twice.
temp->link = NULL;
if (head == NULL)
{
head = temp;
}
else
{
// This is to help traverse the linked list without having to
// manipulate the position of what head points to.
Node *Pos_Indicator = head;
while (Pos_Indicator->link != NULL)
{
Pos_Indicator = Pos_Indicator->link;
}
// We are at the end of the list, it is now safe to add.
Pos_Indicator->link = temp;
// Should probably have a check here for whether it was successful or not.
}
}
I was able to compile and run your code to completion with no other problems. Let me know if this helps!
EDIT: or you know (head = NULL) to (head == NULL) works too :(