I am working on a Linked List assignment. The Load Bids function extracts the data from the CSV file. The Print List function is supposed to print all the bid entries in the list to the console. For some reason, whenever I select the Load Bids option, and then the Print List option from menu, the Print List function is not outputting data, even after I call the Load Bids function. It just prints the default values from the default constructor, which is basically nothing. The Print List function seems to be written correctly, but the data appears to be getting lost somewhere. Can someone help me with this?
#include <algorithm>
#include <iostream>
#include <time.h>
#include "CSVparser.hpp"
using namespace std;
//============================================================================
// Global definitions visible to all methods and classes
//============================================================================
// forward declarations
double strToDouble(string str, char ch);
// define a structure to hold bid information
struct Bid {
string bidId; // unique identifier
string title;
string fund;
double amount;
Bid() {
amount = 0.0;
}
};
//============================================================================
// Linked-List class definition
//============================================================================
/**
* Define a class containing data members and methods to
* implement a linked-list.
*/
class LinkedList {
private:
//Internal structure for list entries, housekeeping variables
struct Node {
Bid bid;
Node *next;
// default constructor
Node() {
next = nullptr;
}
// initialize with a bid
Node(Bid aBid) {
bid = aBid;
next = nullptr;
}
};
Node* head;
Node* tail;
int size = 0;
public:
LinkedList();
virtual ~LinkedList();
void Append(Bid bid);
void Prepend(Bid bid);
void PrintList();
void Remove(string bidId);
Bid Search(string bidId);
int Size();
};
/**
* Default constructor
*/
LinkedList::LinkedList() {
// FIXME (1): Initialize housekeeping variables
//set head and tail equal to null
head = nullptr;
tail = nullptr;
}
/**
* Destructor
*/
LinkedList::~LinkedList() {
// start at the head
Node* current = head;
Node* temp;
// loop over each node, detach from list then delete
while (current != nullptr) {
temp = current; // hang on to current node
current = current->next; // make current the next node
delete temp; // delete the orphan node
}
}
/**
* Append a new bid to the end of the list
*/
void LinkedList::Append(Bid bid) {
// FIXME (2): Implement append logic
//Create new node
Node* new_node = new Node;
//if there is nothing at the head...
if (head == nullptr) {
// new node becomes the head and the tail
head = new_node;
tail = new_node;
}
//else
else {
// make current tail node point to the new node
tail->next = new_node;
// and tail becomes the new node
tail = new_node;
}
//increase size count
size++;
}
/**
* Prepend a new bid to the start of the list
*/
void LinkedList::Prepend(Bid bid) {
// FIXME (3): Implement prepend logic
// Create new node
Node* new_node = new Node;
// if there is already something at the head...
if (head != nullptr) {
// new node points to current head as its next node
new_node->next = head;
}
// head now becomes the new node
head = new_node;
//increase size count
size++;
}
/**
* Simple output of all bids in the list
*/
void LinkedList::PrintList() {
// FIXME (4): Implement print logic
// start at the head
Node* current = head;
// while loop over each node looking for a match
while (current != nullptr) {
//output current bidID, title, amount and fund
cout << current->bid.bidId << " | ";
cout << current->bid.title << " | ";
cout << current->bid.amount << " | ";
cout << current->bid.fund << endl;
//set current equal to next
current = current->next;
}
}
/**
* Remove a specified bid
*
* #param bidId The bid id to remove from the list
*/
void LinkedList::Remove(string bidId) {
// FIXME (5): Implement remove logic
// special case if matching node is the head
if (head->bid.bidId == bidId) {
// make head point to the next node in the list
head->next;
//decrease size count
size--;
//return
return;
}
// start at the head
Node* current = head;
Node* temp = nullptr;
// while loop over each node looking for a match
while (current != nullptr) {
// if the next node bidID is equal to the current bidID
if (current->next->bid.bidId == current->bid.bidId) {
// hold onto the next node temporarily
temp = current->next;
}
// make current node point beyond the next node
current->next->next;
// now free up memory held by temp
free(temp);
// decrease size count
size--;
//return
return;
}
// curretn node is equal to next node
current = current->next;
}
/**
* Search for the specified bidId
*
* #param bidId The bid id to search for
*/
Bid LinkedList::Search(string bidId) {
// FIXME (6): Implement search logic
// special case if matching node is the head
if (head->bid.bidId == bidId) {
// make head point to the next node in the list
head->next;
//decrease size count
size--;
//return
return head->bid;
}
// start at the head of the list
Node* current = head;
// keep searching until end reached with while loop (next != nullptr
while (current != nullptr) {
// if the current node matches, return it
if (current->bid.bidId == bidId) {
return current->bid;
}
// else current node is equal to next node
else {
current = current->next;
}
}
//return bid
return current->bid;
}
/**
* Returns the current size (number of elements) in the list
*/
int LinkedList::Size() {
return size;
}
//============================================================================
// Static methods used for testing
//============================================================================
/**
* Display the bid information
*
* #param bid struct containing the bid info
*/
void displayBid(Bid bid) {
cout << bid.bidId << ": " << bid.title << " | " << bid.amount
<< " | " << bid.fund << endl;
return;
}
/**
* Prompt user for bid information
*
* #return Bid struct containing the bid info
*/
Bid getBid() {
Bid bid;
cout << "Enter Id: ";
cin.ignore();
getline(cin, bid.bidId);
cout << "Enter title: ";
getline(cin, bid.title);
cout << "Enter fund: ";
cin >> bid.fund;
cout << "Enter amount: ";
cin.ignore();
string strAmount;
getline(cin, strAmount);
bid.amount = strToDouble(strAmount, '$');
return bid;
}
/**
* Load a CSV file containing bids into a LinkedList
*
* #return a LinkedList containing all the bids read
*/
void loadBids(string csvPath, LinkedList *list) {
cout << "Loading CSV file " << csvPath << endl;
// initialize the CSV Parser
csv::Parser file = csv::Parser(csvPath);
try {
// loop to read rows of a CSV file
for (int i = 0; i < file.rowCount(); i++) {
// initialize a bid using data from current row (i)
Bid bid;
bid.bidId = file[i][1];
bid.title = file[i][0];
bid.fund = file[i][8];
bid.amount = strToDouble(file[i][4], '$');
// cout << bid.bidId << ": " << bid.title << " | " << bid.fund << " | " <<
bid.amount << endl;
// add this bid to the end
list->Append(bid);
}
} catch (csv::Error &e) {
std::cerr << e.what() << std::endl;
}
}
/**
* Simple C function to convert a string to a double
* after stripping out unwanted char
*
* credit: http://stackoverflow.com/a/24875936
*
* #param ch The character to strip out
*/
double strToDouble(string str, char ch) {
str.erase(remove(str.begin(), str.end(), ch), str.end());
return atof(str.c_str());
}
/**
* The one and only main() method
*
* #param arg[1] path to CSV file to load from (optional)
* #param arg[2] the bid Id to use when searching the list (optional)
*/
int main(int argc, char* argv[]) {
// process command line arguments
string csvPath, bidKey;
switch (argc) {
case 2:
csvPath = argv[1];
bidKey = "98109";
break;
case 3:
csvPath = argv[1];
bidKey = argv[2];
break;
default:
csvPath = "eBid_Monthly_Sales_Dec_2016.csv";
bidKey = "98109";
}
clock_t ticks;
LinkedList bidList;
Bid bid;
int choice = 0;
while (choice != 9) {
cout << "Menu:" << endl;
cout << " 1. Enter a Bid" << endl;
cout << " 2. Load Bids" << endl;
cout << " 3. Display All Bids" << endl;
cout << " 4. Find Bid" << endl;
cout << " 5. Remove Bid" << endl;
cout << " 9. Exit" << endl;
cout << "Enter choice: ";
cin >> choice;
switch (choice) {
case 1:
bid = getBid();
bidList.Append(bid);
displayBid(bid);
break;
case 2:
ticks = clock();
loadBids(csvPath, &bidList);
cout << bidList.Size() << " bids read" << endl;
ticks = clock() - ticks; // current clock ticks minus starting clock ticks
cout << "time: " << ticks << " milliseconds" << endl;
cout << "time: " << ticks * 1.0 / CLOCKS_PER_SEC << " seconds" << endl;
break;
case 3:
bidList.PrintList();
break;
case 4:
ticks = clock();
bid = bidList.Search(bidKey);
ticks = clock() - ticks; // current clock ticks minus starting clock ticks
if (!bid.bidId.empty()) {
displayBid(bid);
} else {
cout << "Bid Id " << bidKey << " not found." << endl;
}
cout << "time: " << ticks << " clock ticks" << endl;
cout << "time: " << ticks * 1.0 / CLOCKS_PER_SEC << " seconds" << endl;
break;
case 5:
bidList.Remove(bidKey);
break;
}
}
cout << "Good bye." << endl;
return 0;
}
I altered the Append function by adding a couple of lines after creating the new node and it looks like the problem was solved. Here is the new function.
void LinkedList::Append(Bid bid) {
// FIXME (2): Implement append logic
//Create new node
Node* new_node = new Node;
new_node->bid = bid;
new_node->next = nullptr;
//if there is nothing at the head...
if (head == nullptr) {
// new node becomes the head and the tail
head = new_node;
tail = new_node;
}
//else
else {
// make current tail node point to the new node
tail->next = new_node;
// and tail becomes the new node
tail = new_node;
}
//increase size count
size++;
}
Related
I'm making a program with sorted list that has a variety of functions I'm supposed to build in the header source file. So far I have everything working perfectly but when I ask for the min value the first time it gives me the second highest value, 1, instead of the lowest which is 0. It gives me the lowest number the second time I ask, but I assume it's because it's not reaching the end of the linked list, but I'm not sure what to change.
Here's the header
#include <iostream>
using std::cout;
using std::endl;
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
class LinkedList
{
private:
struct Node
{
int data;
Node *next;
};
int size;
Node *head, *tail;
public:
LinkedList();
~LinkedList();
// misc
void display();
// sorting and searching
// reverse --> sorting in descending
int linearSearch(int key);
void sort();
void reverse();
// various math
int min();
int max();
int mean();
// adding
void append(int num);
void insert(int num, int pos);
// removing
void pop();
void remove(int pos);
};
#endif // LINKEDLIST_H
source file
#include "linkedlist.h"
// GIVEN TO STUDENTS
LinkedList::LinkedList()
{
head = nullptr;
tail = nullptr;
size = 0;
}
LinkedList::~LinkedList()
{
if(head != nullptr)
{
Node *temp;
while(head != nullptr)
{
temp = head->next;
// deletes head
delete head;
// goes to next element
head = temp;
}
}
}
void LinkedList::display()
{
Node *temp = head;
for(int i = 0; i < size; i++)
{
cout << temp->data << "\t";
temp = temp->next;
}
cout << endl;
}
void LinkedList::append(int num)
{
// list is empty
if(head == nullptr)
{
head = new Node;
head->data = num;
head->next = nullptr;
// sets tail to head
tail = head;
}
else
{
// creates new node
Node *temp = new Node;
// sets new node data
temp->data = num;
temp->next = nullptr;
// sets previous tail link to new node
tail->next = temp;
// sets this node to new tail
tail = temp;
}
// increments size
size++;
}
void LinkedList::pop()
{
if(size > 1)
{
Node *temp = head;
// loops to node before tail
while(temp->next->next != nullptr)
{
temp = temp->next;
}
// deletes tail
delete tail;
// sets new tail
tail = temp;
tail->next = nullptr;
}
// if there's only one item
else if(size == 1)
{
Node *temp = tail;
// head and tail are now null
head = nullptr;
tail = nullptr;
// deletes node
delete temp;
}
size--;
}
// END GIVEN TO STUDENTS
void LinkedList::insert(int num, int pos)
{
if(pos ==0)
{
Node *temp=new Node;
temp->data=num;
temp->next=head;
head=temp;
}
if(pos>1)
{
Node *pre=new Node;
Node *cur=new Node;
Node *temp=new Node;
cur=head;
for(int i=1;i<pos+1;i++)
{
pre=cur;
cur=cur->next;
}
temp->data=num;
pre->next=temp;
temp->next=cur;
}
size++;
}
int LinkedList::linearSearch(int key)
{
Node *temp = head;
for(int i = 0; i < size; i++)
{
if(temp->data == key)
{
return i;
}
temp = temp->next;
}
return -1;
}
void LinkedList::reverse()
{
Node* temp = head;
// Traverse the List
while (temp)
{
Node* min = temp;
Node* r = temp->next;
// Traverse the unsorted sublist
while (r)
{
if (min->data < r->data)
min = r;
r = r->next;
}
// Swap Data
int x = temp->data;
temp->data = min->data;
min->data = x;
temp = temp->next;
}
}
void LinkedList::remove(int pos)
{
Node *temp = head;
if(pos ==0)
{
head = temp->next;
free(temp);
}
if(pos>1)
{
Node *current=new Node;
Node *previous=new Node;
current=head;
for(int i=1;i<pos+1;i++)
{
previous=current;
current=current->next;
}
previous->next=current->next;
}
size--;
}
void LinkedList::sort()
{
Node* temp = head;
// Traverse the List
while (temp) {
Node* min = temp;
Node* r = temp->next;
// Traverse the unsorted sublist
while (r) {
if (min->data > r->data)
min = r;
r = r->next;
}
// Swap Data
int x = temp->data;
temp->data = min->data;
min->data = x;
temp = temp->next;
}
}
int LinkedList::min()
{
int min = INT_MAX;
for(Node* temp = head; temp != nullptr; temp = temp->next)
{
if (head->data < min)
{
min = temp->data;
}
}
return min;
}
int LinkedList::max()
{
int max = INT_MIN;
for (Node* temp = head; temp != nullptr; temp = temp->next)
{
if (temp->data > max)
{
max = temp->data;
}
}
return max;
}
int LinkedList::mean()
{
if (!head)
return -1;
int count = 0; // Initialize count
int sum = 0;
float avg = 0.0;
struct Node* current = head; // Initialize current
while (current != NULL) {
count++;
sum += current->data;
current = current->next;
}
// calculate average
avg = (double)sum / count;
return avg;
}
and main
#include <iostream>
#include "linkedlist.h"
using namespace std;
int main()
{
LinkedList nums;
// adding through append
nums.append(8);
nums.append(6);
nums.append(7);
nums.append(8);
nums.append(0);
nums.append(9);
// displays list
cout << "List after append: " << endl;
nums.display();
cout << endl;
// adding through insert
nums.insert(1, 0);
nums.insert(5, 4);
nums.insert(3, 7);
// displays list
cout << "List after inserting: " << endl;
nums.display();
cout << endl;
// testing searching
cout << "Testing linear search:" << endl;
int pres = nums.linearSearch(7);
if(pres < 0)
{
cout << "7 is not present in the list." << endl;
}
else
{
cout << "7 can be found at location " << pres << endl;
}
pres = nums.linearSearch(5);
if(pres < 0)
{
cout << "5 is not present in the list." << endl;
}
else
{
cout << "5 can be found at location " << pres << endl;
}
cout << endl;
// does math
cout << "Minimum, maximum, and average before removing any items: " << endl;
cout << "Min: " << nums.min() << endl;
cout << "Max: " << nums.max() << endl;
cout << "Mean: " << nums.mean() << endl << endl;
// displays items reversed
cout << "Items reversed: " << endl;
nums.reverse();
nums.display();
cout << endl;
// removing through pop
nums.pop();
nums.pop();
// displays list
cout << "List after popping: " << endl;
nums.display();
cout << endl;
// removing through remove
nums.remove(0);
nums.remove(2);
nums.remove(4);
// displays list
cout << "List after removing: " << endl;
nums.display();
cout << endl;
// displays items sorted
cout << "Items sorted: " << endl;
nums.sort();
nums.display();
cout << endl;
// does math
cout << "Minimum, maximum, and average after removing items: " << endl;
cout << "Min: " << nums.min() << endl;
cout << "Max: " << nums.max() << endl;
cout << "Mean: " << nums.mean() << endl << endl;
// testing searching
cout << "Testing linear search:" << endl;
pres = nums.linearSearch(7);
if(pres < 0)
{
cout << "7 is not present in the list." << endl;
}
else
{
cout << "7 can be found at location " << pres << endl;
}
pres = nums.linearSearch(5);
if(pres < 0)
{
cout << "5 is not present in the list." << endl;
}
else
{
cout << "5 can be found at location " << pres << endl;
}
return 0;
}
I think you have a typo in your min function, it always compares head-data to the min instead of the temp node. Try this:
int LinkedList::min()
{
int min = INT_MAX;
for(Node* temp = head; temp != nullptr; temp = temp->next)
{
min = temp->data < min ? temp->data : min;
}
return min;
}
below is my current in-progress code converting a singly linked to a doubly linked list. I haven't touched the delete function yet. I've gotten insert in empty list, end of list, and beginning of list apparently working.
However nodes inserting in the middle seemingly fail to create a link to the previous node. My debugging lines I inserted seem to show both the n->next and n-> prev with the correct memory address, but when I go to reverseprint, any nodes inserted in the middle are missed and the links are gone. Where am I going wrong in regards to this?
Code below:
#include <iostream>
#include <string>
using namespace std;
// define a node for storage and linking
class node {
public:
string name;
node *next;
node *prev;
};
class linkedList {
public:
linkedList() :top(NULL) {}
bool empty() { return top == NULL; }
node *getTop() { return top; }
node *getEnd() { return end; }
void setTop(node *n) { top = n; }
void setEnd(node *p) { end = p; }
void add(string);
int menu();
void remove(string);
~linkedList();
void reversePrint();
friend ostream& operator << (ostream&, const linkedList&); // default output is in-order print.
private:
node *top;
node *end;
};
void main() {
linkedList l;
cout << l.empty() << endl;
int option = 0;
string s;
bool go = true;
while (go) {
option = l.menu();
switch (option) {
case 1: cout << "enter a name: "; cin >> s; l.add(s); break;
case 2: cout << "enter name to be deleted: "; cin >> s; l.remove(s); break;
case 3: cout << l; break;
//case 4: cout << "can not be done with a singly linked list" << endl;
case 4: l.reversePrint(); break;
case 5: cout << "exiting" << endl; go = false; break;
}
}
system("pause");
}
void linkedList::remove(string s) {
bool found = false;
node *curr = getTop(), *prev = NULL;
while (curr != NULL) {
// match found, delete
if (curr->name == s) {
found = true;
// found at top
if (prev == NULL) {
node *temp = getTop();
setTop(curr->next);
delete(temp);
// found in list - not top
}
else {
prev->next = curr->next;
delete(curr);
}
}
// not found, advance pointers
if (!found) {
prev = curr;
curr = curr->next;
}
// found, exit loop
else curr = NULL;
}
if (found)cout << "Deleted " << s << endl;
else cout << s << " Not Found " << endl;
}
void linkedList::add(string s) {
node *n = new node();
n->name = s;
n->next = NULL;
n->prev = NULL;
// take care of empty list case
if (empty()) {
top = n;
end = n;
// take care of node belongs at beginning case
}
else if (getTop()->name > s) {
n->next = getTop();
n->prev = NULL;
setTop(n);
node *temp;
temp = n->next;
temp->prev = n;
// take care of inorder and end insert
}
else {
// insert in order case
node *curr = getTop(), *prev = curr;
while (curr != NULL) {
if (curr->name > s)break;
prev = curr;
curr = curr->next;
}
if (curr != NULL) { // search found insert point
n->next = curr;
cout << n->name << " " << n << " prev " << prev << " " << prev->name << endl;
n->prev = prev;
prev->next = n;
cout << "n->prev is: " << n->prev << " " << n->prev->name << endl;
cout << "n->next is: " << n->next << " " << n->next->name << endl;
}
// take care of end of list insertion
else if (curr == NULL) {// search did not find insert point
prev->next = n;
n->prev = prev;
cout << "n->prev is: " << n->prev << " " << n->prev->name << endl;
setEnd(n);
}
}
}
ostream& operator << (ostream& os, const linkedList& ll) {
//linkedList x = ll; // put this in and the code blows up - why?
node *n = ll.top;
if (n == NULL)cout << "List is empty." << endl;
else
while (n != NULL) {
os << n->name << endl;
os << n << endl;
if (n->next != NULL) {
os << "next is " << n->next << endl;
}
n = n->next;
}
return os;
}
void linkedList::reversePrint() {
node *n = end;
if (n == NULL)cout << "List is empty." << endl;
else
while (n != NULL) {
//cout << n->name << endl;
cout << "memory address of " << n->name << " is " << n << endl;
if (n->prev != NULL) {
cout << "prev is " << n->prev << endl;
}
n = n->prev;
}
return;
}
// return memory to heap
linkedList::~linkedList() {
cout << "~linkedList called." << endl;
node *curr = getTop(), *del;
while (curr != NULL) {
del = curr;
curr = curr->next;
delete(del);
}
}
int linkedList::menu() {
int choice = 0;
while (choice < 1 || choice > 5) {
cout << "\nEnter your choice" << endl;
cout << " 1. Add a name." << endl;
cout << " 2. Delete a name." << endl;
cout << " 3. Show list." << endl;
cout << " 4. Show reverse list. " << endl;
cout << " 5. EXIT " << endl;
cin >> choice;
}
return choice;
}
You are not setting the prev of the current in insertion into middle, just do:
n->next = curr;
curr->prev = n; // <-- this
I am doing an assignment of linked list of strings. Everything seems to work fine until I get to the sorting part. I am using classes as well. I already have 2 functions. The first one minimum(string) where it returns the string that would come first in alphabetical order.
This functions works fine. I also have a function remove(string) where it removes a node containing the given string from the linked list. It returns true if successful, otherwise false (if string was not in the list), in this case I have to erase the string returned by the minimum(string) function. The function I am having trouble is sort().
It wants me to define a StringNode pointer to be the head of a new list (the empty list) then I need a loop where I will call the functions of minimum(string) and remove(string). Inside the loop I also need to insert this node into the proper position in the new list (append it to the end). The old head pointer (now empty) must point to the new list.
I am very confused about this, so far I have this:
void StringList::sort()
{
StringNode *newList = new StringNode;
newList = NULL;
string mini;
bool removed;
while (newList->next != NULL)
{
StringNode *newList2 = new StringNode;
StringNode *p = head;
mini = minimum();
p->data = mini;
p->next = NULL;
newList2 = newList2->next;
newList2->next = p;
removed = remove(mini);
newList = newList2;
}
}
How I understand is: I need to create a new node which will be an empty list meaning newList->next = NULL; then on the loop I need to create another new node, and a pointer that will point to the head of new node inside the loop. I need to make the value given by the minimum be stored in the pointer p and the pointer to point back to the new node.
Any help will be greatly appreciated. Thanks!
Here is the hole program.
// StringList.cpp
#include <iomanip>
#include <iostream>
#include <sstream>
#include "StringList.h"
using namespace std;
//******************************************************************************
// StringList: creates an empty list
//******************************************************************************
StringList::StringList()
{
head = NULL;
}
//******************************************************************************
// StringList: deallocates all the nodes in StringList
//******************************************************************************
StringList::~StringList()
{
StringNode *p;
StringNode *n;
p = head;
while (p != NULL)
{
n = p->next;
delete p;
p = n;
}
}
//******************************************************************************
// count: returns the total number of nodes in the list.
//******************************************************************************
int StringList::count()
{
int count = 0;
StringNode *p;
p = head;
while ( p != NULL )
{
count++;
p = p->next;
}
return count;
}
//******************************************************************************
// add: adds a new node to the beginning of the list.
//******************************************************************************
void StringList::add(string movie)
{
StringNode *newNode = new StringNode;
newNode->data = movie;
newNode->next = head;
head = newNode;
}
//******************************************************************************
// remove: removes a node containing the string from linked list
// returns true if successful or false the string is not in the list
//******************************************************************************
bool StringList::remove(string movie)
{
StringNode *p = head;
StringNode *n = NULL;
while (p != NULL && p->data != movie )
{
n = p;
p = p->next;
if (p == NULL )
{
return false;
}
else if (p->data == movie)
{
n->next = p->next;
delete p;
return true;
}
}
}
//******************************************************************************
//display: Displays the strings in the list.
//******************************************************************************
void StringList::display()
{
StringNode *p;
p = head;
while (p != NULL)
{
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
//******************************************************************************
//minimum: return the string in alphabetical order
//******************************************************************************
string StringList::minimum()
{
StringNode *p = head;
string minimum = p->data;
while (p->next != NULL)
{
p = p->next;
if(minimum > p->data)
{
minimum = p->data;
}
}
return minimum;
}
//******************************************************************************
//sort: will call the minimum function and remove function
//******************************************************************************
void StringList::sort()
{
StringNode* newhead; // create a new head pointer
string mini;
bool removed;
//adding the first node to the new list.
StringNode *newnode = new StringNode;
mini = minimum(); // get the minimum from the existing linked list
newnode->data = mini;
newnode->next = NULL;
newhead=newnode; //add the minimum node to the new list(with the newhead)
StringNode *p = newhead;
while (head != NULL) // loop should run until there's no node left in the original list
{
StringNode *newnode = new StringNode;
mini = minimum(); // get the minimum from the existing linked list
newnode->data = mini;
newnode->next = NULL;
p->next=newnode; //add the minimum node to the new list(with the newhead pointer)
removed = remove(mini);
p=p->next;
}
head=newhead; //finally change the head pointer, so that the head now points to sorted list.
}
// StringList.h
#ifndef STRINGLIST_H_INCLUDED
#define STRINGLIST_H_INCLUDED
#include <string>
using namespace std;
class StringList
{
private:
struct StringNode // the Nodes of the linked list
{
string data; // data is a string
StringNode *next; // points to next node in list
};
StringNode *head; // the head pointer
public:
StringList();
~StringList();
int count();
void add(string);
bool remove(string);
void display();
string minimum();
void sort();
};
#endif // STRINGLIST_H_INCLUDED
//Driver.cpp
#include<iostream>
#include<iomanip>
using namespace std;
#include "StringList.h"
int main()
{
//testing StringList
StringList slist;
string movie1 = "Star Wars";
string movie2 = "Fargo";
string movie3 = "Back to the Future";
string movie4 = "Titanic";
// Testing add/display/count
cout << "Testing add/display/count: " << endl;
cout << "count is: " << slist.count() << endl;
slist.add(movie1);
slist.display();
cout << "count is: " << slist.count() << endl;
slist.add(movie2);
slist.display();
cout << "count is: " << slist.count() << endl;
slist.add(movie3);
slist.add(movie4);
slist.display();
cout << "count is: " << slist.count() << endl;
// Testing remove
cout << endl;
cout << "Testing remove: " << endl;
bool delResult;
delResult = slist.remove(movie4);
cout << "remove result movie4 = " << boolalpha << delResult << endl;
delResult = slist.remove(movie3);
cout << "remove result movie3 = " << boolalpha << delResult << endl;
delResult = slist.remove("Not There");
cout << "remove result Not There = " << boolalpha << delResult << endl;
cout << "display after remove: " << endl;
slist.display();
cout << "count is: " << slist.count() << endl;
//Testing minimum
cout << endl;
cout << "Testing minimum: " << endl;
cout << "Test minimum 1: " << endl;
slist.display();
cout << "minimum: " << boolalpha << slist.minimum() << endl;
cout << "Test minimum 2: " << endl;
slist.add(movie4);
slist.display();
cout << "minimum: " << boolalpha << slist.minimum() << endl;
cout << "Test minimum 3: " << endl;
slist.add(movie3);
slist.display();
cout << "minimum: " << boolalpha << slist.minimum() << endl;
//Testing sort and display
cout << endl;
cout << "Testing sort/display: " << endl;
slist.sort();
slist.display();
cout << endl;
cout << "Testing sort/display after add: " << endl;
slist.add("Jurassic Park");
slist.display();
cout << "now sorted: " << endl;
slist.sort();
slist.display();
}
your remove function has small fault. You didn't take care of the possibility of removing the first node.
bool StringList::remove(string movie)
{
StringNode *p = head;
StringNode *n = NULL;
if(p->data==movie) //added this condition
{
head=head->next;
delete p;
return true;
}
while (p != NULL && p->data != movie )
{
n = p;
p = p->next;
if (p == NULL )
{
return false;
}
else if (p->data == movie)
{
n->next = p->next;
delete p;
return true;
}
}
}
final sort function. The objective is to sort the existing list by using the minimum and remove functions and get the new sorted list. You need to get minimum from the existing list and keep adding them at the end of the new list. And finally change the head pointer to point it to the new list.
The while loop should run until the existing list becomes empty.
void StringList::sort()
{
string mini;
bool removed;
//adding the first node to the new list.
StringNode *newnode1 = new StringNode;
mini = minimum(); // get the minimum from the existing linked list
newnode1->data = mini;
newnode1->next = NULL;
removed =remove(mini);
StringNode *p = newnode1;
while (head != NULL) // the loop should run until the original list is empty
{
StringNode *newnode = new StringNode;
mini = minimum(); // get the minimum from the existing linked list
newnode->data = mini;
newnode->next = NULL;
p->next=newnode; //add the minimum node to the new list
removed = remove(mini);
p=p->next;
}
head=newnode1; //finally change the head pointer, so that the head now points to sorted list.
}
I am having two issues with my c++ code (The test file is below):
I can't seem to figure out why its not breaking out of the while loop, when running, its stuck on the loop "7 versus 325".
So it should go into the next node of temp, which would be null, and then jump into the section where it adds it to the end of the queue. But its just looping and looping.
My second issue is with the the function I have commented out, queue1.back, whenever that is ran, it just errors out and gives what appears to be the address, but the .front() function works just fine.
The Test File I am working with is like this:
89 Alex
325 Rob
72 Joy
91 Bob
using namespace std;
class Person
{
friend class Pqueue;
public:
int priority;
string name;
};
class PQueue
{
friend class Person;
private:
//Structure for my linked list.
typedef struct node {
Person data;
struct node *next;
}Node, *NodePtr;
Node *head, *tail;
public:
//Prototype Functions
PQueue(void); //Initializer function
bool empty(void); //Test if empty
int size(void); //Return size
void enqueue(Person *); //Insert Node
void dequeue(void); //Remove Node
Person* front(void); //Access Next Node
Person* back(void); //Access last node
};
PQueue::PQueue()
{
head = NULL;
tail = NULL;
}
bool PQueue::empty(){
return (head == NULL);
}
void PQueue::enqueue(Person *myPerson){
NodePtr np = (NodePtr) malloc(sizeof(Node));
np->data = *myPerson;
np->next = NULL;
if(empty())
{
cout << "Making into creating the first node, of the linked list" <<endl;
head = np;
tail = np;
}
else { //Queue has more the one node
Node* temp = head;
if(np->data.priority > temp->data.priority) //If the priority is greater then the rest.
{
head = temp; //Saving my head pointer
head->data = np->data; //Assigning new Data to the head pointer
head->next = temp; //Assigning the rest of the linked list back into head.
cout << "Making into creating the first node again, having to reassign." <<endl;
}
else{
//Searching where to place the node.
while(temp->data.priority > np->data.priority) //Searching if the next priority is higher then the passed.
{
cout << "Inside the while loop: " << np->data.priority << " versus "<<temp->data.priority <<endl;
if(temp->next == NULL)
break;
temp = temp->next;
}
if(temp->next == NULL && np->data.priority < temp->data.priority) //Inserting at the end.
{
cout << "Making into creating the last node" <<endl;
tail->next = np;
cout << "Passing the function of creating the last node" <<endl;
}
else //Inserting into the middle of the function.
{
cout << "Inserting in the middle of the queue" <<endl;
np->next = temp->next;
temp->next = np;
}
}
}
}
void PQueue::dequeue(){
if(empty()){
cout << "\nAttempt to remove from an empty list." << endl;
exit(1);
}
Person hold = head->data;
NodePtr temp = head;
head=head->next;
if (head == NULL) tail = NULL;
free(temp);
}
Person* PQueue::front(){
//Person &temp = head->next->data;
//Person &temp = head->data;
Person &temp = head->data;
return &temp;
}
Person* PQueue::back(){
if(empty()){
cout << "\nNo entries in list." << endl;
exit(1);
}
Person &temp = tail->data;
return &temp;
}
int main() {
cout << "Starting main" << endl;
PQueue queue1; //Creating my queue.
cout << "Created Queue" << endl;
Person tempPerson;
ifstream inFile;
inFile.open("/tmp/temp");
cout << "going into while loop" << endl;
while (inFile >> tempPerson.priority >> tempPerson.name){
cout << "The priority is " << tempPerson.priority << " the name is " << tempPerson.name <<endl;
queue1.enqueue(&tempPerson);
}
//Testing Section, trying to get .front and .back to work.
Person *testPerson;
testPerson = queue1.front();
cout << "The TEST priority is " << testPerson->priority << " the TEST name is " << testPerson->name <<endl;
/**
Person *tailPerson;
testPerson = queue1.back();
cout << "The TEST priority is " << tailPerson->priority << " the TEST name is " << tailPerson->name <<endl;
**/
queue1.dequeue();
queue1.dequeue();
queue1.dequeue();
return 0;
}
When you add a new head entry to a non-empty list, you're mistakenly setting the next pointer to point right back at the node it's in, rather than setting it to point at the rest of the linked list like you intended.
head = temp; //Saving my head pointer
head->next = temp; //Assigning the rest of the linked list back into head.
I'm new to C++ and I'm trying to code a linked-list based queue. My test program worked fine until I added delete to the dequeue function. Then I get the error:
malloc: *** error for object 0x7f8a61403a00: pointer being freed was not allocated
Any help would be appreciated.
#include <string>
#include "queue.h"
#include <iostream>
using namespace std;
Queue::Queue() { // Constructs a new empty queue.
current_size = 0; // number of elements in queue
front_p = NULL; // first element in queue
back_p = NULL; // last element in queue
}
Queue::Queue( const Queue& q ) {// Copy constructor.
// nothing to copy if queue empty
if (q.current_size == 0) {
return;
}
// queue not empty
else {
node * p = q.front_p;
node * n;
// assign front pointer
n = new node(p -> data, NULL);
front_p = n;
p = p -> next;
// middle elements
while (p -> next != NULL) {
n -> next = p;
n = new node(p -> data, NULL);
p = p -> next;
}
// assign back pointer
n = new node(p -> data, NULL);
back_p = n;
current_size = q.current_size;
}
}
void Queue::enqueue( int item ) { // Enqueues <item> to back
node * n = new node(item, NULL);
// first item in queue, front & back ptrs point to same element
if (back_p == NULL) {
front_p = n;
back_p = n;
}
else {
back_p -> next = n;
back_p = n;
}
current_size++;
}
int Queue::dequeue() { // removes and returns the front item.
// empty queue
if (current_size == 0) {
return -1;
}
int item = front();
node * p = front_p;
if (current_size == 1) {
front_p = NULL;
back_p = NULL;
delete p;
current_size--;
return item;
}
else {
front_p = front_p -> next;
delete p;
current_size--;
return item;
}
}
test file
//test file
#include <iostream>
#include "queue.h"
using namespace std;
int main(void) {
Queue q1;
cout << "Create a new queue q1" << endl;
cout << "Size of q1 \t" << q1.size() << endl;
cout << "Is q1 empty? \t" << q1.empty() << endl;
cout << endl << endl;
cout << "enqueue \t1,2,3,4,5" << endl;
q1.enqueue(1);
q1.enqueue(2);
q1.enqueue(3);
q1.enqueue(4);
q1.enqueue(5);
cout << "front of q1 \t" << q1.front() << endl;
cout << "size of q1 \t" << q1.size() << endl << endl;
cout << "q2 is a deep copy of q1" << endl;
Queue q2(q1);
cout << "front of q2 \t" << q2.front() << endl;
cout << "size of q2 \t" << q2.size() << endl << endl;
cout << "removed 4 from q1" << endl;
q1.remove(4);
cout << "removed 2 from q2" << endl;
q2.remove(2);
cout << endl;
cout << "print out remaining elements of q1" << endl;
int N = q1.size();
for(int i=0; i < N; i++) {
cout << q1.dequeue() << " ";
}
cout << endl << endl;
cout << "print out remaining elements of q2" << endl;
N = q2.size();
for(int i=0; i < N; i++) {
cout << q2.dequeue() << " ";
}
cout << endl;
}
header file
class Queue
{
public:
Queue(); // Constructs a new empty queue.
Queue( const Queue& q );// Copy constructor.
~Queue();// Destructor.
void enqueue( int item ); // Enqueues <item>.
int dequeue(); // Dequeues the front item.
int front(); // Returns the front item without dequeuing it.
bool empty(); // Returns true iff the queue contains no items.
int size(); // Returns the current number of items in the queue.
bool remove(int item); // If <item> occurs in the queue, removes the
// first occurrence of <item> and returns true; otherwise returns false.
private:
class node // node type for the linked list
{
public:
node(int new_data, node * next_node){
data = new_data ;
next = next_node ;
}
int data ;
node * next ;
};
node * front_p ; // pointer to the (node containing the) next item
// which to be dequeud, or NULL if the queue is empty.
node * back_p ; // pointer to the (node containing the) last item
// which was enqueued, or NULL if the queue is empty.
int current_size ; // current number of elements in the queue.
};
There are other issues with the code, but the most immediate one is that your copy-constructor is broken.
In this cycle
while (p -> next != NULL) {
n -> next = p;
n = new node(p -> data, NULL);
p = p -> next;
}
p is a pointer to an element of a source queue q. Meanwhile, n is an element of the new queue. By doing n -> next = p; you are making the new queue nodes to link into the source queue node chain. This creates a completely nonsensical node linkage structure, which falls apart later.