I am trying to read a text file,sort it each user with respect to their number in text file then add it to the linked list.then display it again respect to user number of each node in descending order.also i am trying to add functions to edit like deleting or updating the content.
txt file is like
John Doe ; 10
Sally Tully ; 5
James Watson ; 12
what i have achieved is this:
list.h:
#include<string>
#ifndef LIST_H
#define LIST_H
class list{
private:
struct node{
std::string data;
node* next;
};
typedef struct node* nodePtr;
nodePtr head;
nodePtr curr;
nodePtr temp;
public:
list();
void AddNode(std::string addData);
void DeleteNode(std::string delData);
void PrintList();
};
#endif
list.cpp
#include <cstdlib>
#include <iostream>
#include "list.h"
using namespace std;
list::list(){ //constructor
head = NULL;
curr= NULL;
temp=NULL;
}
void list::AddNode(string addData){
nodePtr n = new node; //nodePtr is node*
n->next=NULL; //find node n is pointing to, access its next element make it point to null
n->data= addData;
if(head != NULL) { // if we have at least 1 element in the list .
curr = head; // take the current pointer we are working with and make it same with head pointer pointing to.(current= front of list)
while(curr->next !=NULL){ // are we at the end of the list.
curr = curr->next;//we are not end of the list.curr pointer points next node.
}
curr->next = n;
}else{ //if we dont have at least 1 element in the list.
head =n;
}
}
void list::DeleteNode(string delData){
nodePtr delPtr = NULL;
temp = head;
curr = head;
while(curr != NULL && curr->data != delData){ // look for data user wants to delete
temp = curr;
curr = curr->next;
}
if(curr == NULL){ // we cant find we are looking for.
cout << delData << "not in list"<<endl;
delete delPtr;
}else{ // we found it
delPtr = curr;
curr = curr->next; // with those 2 lines we are patching the hole in the list.
temp->next = curr;
if(delPtr == head){
head = head->next;
temp = NULL;
}
delete delPtr;
cout<<delData<<"deleted"<<endl;
}
}
void list::PrintList(){
curr = head;
while(curr !=NULL){
cout<<curr->data<<endl;
curr = curr->next;
}
}
int main(){
list mylist;
mylist.AddNode("hello");
mylist.AddNode("how u doin");
mylist.AddNode("good");
mylist.PrintList();
return 0;
}
after reading the txt file should i put them into a vector(or directly to list) then sort then put to linked list ? i guess its wrong i should put them directly then sort before printing on screen. also i dont have any idea how to do updating node by user input function.
update:
I achieved adding content to linked list from txt file.
string file;
ifstream filein;
cout << "Enter file name:"<<endl;
cin >> file;
filein.open(file);
for(;filein.fail();)
{
cout << "Cannot open the file"<<endl;
cout << "Enter file name:"<<endl;
cin >> file;
filein.open(file);
}
string cline;
string cname;
string csurname;
int money;
string smoney;
string lastdata;
char delimiter=';';
while (std::getline(filein, cline)){
std::istringstream iss(cline);
while(iss >> cname >> csurname >> delimiter >> money){
ostringstream temp; // int to string
temp<<money;
smoney=temp.str();
lastdata = cname+" "+csurname+" "+smoney;
mylist.AddNode(lastdata);
}
}
mylist.PrintList();
now it adds like
john doe 10
sally tully 5
the problem is how im gonna reach this 10 and sort them while printing on screen
One way o solve the problem is to create two kinds of methods, one that deals with the comparison and other one that sort the linked list.
The below method deals with comparison. In this case it is comparing the length of the string, but it could be anything.
bool list::IsGreater(nodePtr a, nodePtr b)
{
if (a->data.length() > b->data.length())
return true;
return false;
}
The second method sorts the linked list. Even if there is a sort method, the easiest way is to keep the list sorted during the method AddNode.
void list::SortList() {
for (nodePtr i = head; i != NULL; i = i->next) {
nodePtr prev = NULL;
for (nodePtr j = head; j != NULL && j->next != NULL; j = j->next) {
if (IsGreater(j, j->next)) {
if (prev)
prev->next = j->next;
else
head = j->next;
nodePtr tmp = j->next;
j->next = j->next->next;
tmp->next = j;
j = tmp;
}
if (prev == NULL)
prev = head;
else
prev = j;
}
prev = i;
}
}
Related
I'm trying to transition from an almost entirely Java background to getting comfortable with C++. I'm practicing by trying to build a basic Linked List.
#include <iostream>
#include <string>
using namespace std;
struct node
{
string data;
node *next = NULL;
};
class linkedlist
{
public:
node *head;
public:
linkedlist()
{
head = NULL;
}
void addNode(string s)
{
node *newNode = new node;
newNode->data = s;
if(head == NULL)
head = newNode;
else
{
node *temp = head->next;
while(temp != NULL)
temp = temp->next;
temp = newNode;
}
}
void printList()
{
node *temp = head;
while(temp != NULL)
{
cout << temp->data << '\n';
temp = temp->next;
}
}
};
The issue at hand is that once I add a new node using void addNode(string s), it does not appear when I attempt to print the list (starting from the head) with void printList().
For example:
int main(int argc, const char * argv[])
{
int n;
string str;
linkedlist list;
cout << "Please enter the number of strings you'd like to enter:\n";
cin >> n;
for(int i = 0;i < n;i++)
{
string temp;
cout << "Enter string #" << i + 1 << '\n';
cin >> temp;
list.addNode(temp);
}
cout << "This is your linked list: ";
list.printList();
return 0;
}
Using main() above, my results become:
This is your linked list:
(string 1)
I'm pretty certain I'm using pointers improperly here but I don't see why. I've done as much digging as I can on my own for some clarification on how I could be doing this wrong but I'm coming up blank.
Thanks for any clarification you folks can provide.
The problem is here:
node *temp = head->next;
while(temp != NULL)
temp = temp->next;
temp = newNode;
You're traversing the list, then setting temp to the value of the newNode. When temp goes out of scope, the value for newNode isn't stored anyplace.
What you want to do is set the next pointer of the last node to the value of newNode, i.e.
node *temp = head;
while(temp->next != NULL)
temp = temp->next;
temp->next = newNode;
The code above traverses the list until it finds a node that doesn't have a next node, and sets its next node to the newNode, thus adding it to the list.
How do I make my program print the Linked List backwards? I got the printForward function working fine but the printBackwards function just doesn't seem to do anything. I think I'm on the right track but I'm a little stuck right now. I think the while loop isn't running because temp is NULL for some reason.
Any help would be great.
Thanks
List.h
#include <iostream>
using namespace std;
class LinkedList
{
private:
struct Node
{
int data;
Node * next;
Node * prev;
};
Node * head, *tail;
public:
LinkedList();
bool addAtBeginning(int val);
bool remove(int val);
void printForward() const;
void printBackward() const;
};
#endif
List.cpp
#include "List.h"
LinkedList::LinkedList()
{
head = NULL;
tail = NULL;
}
bool LinkedList::addAtBeginning(int val)
{
Node* temp;
temp = new Node;
temp->data = val;
temp->next = head;
head = temp;
return false;
}
bool LinkedList::remove(int val)
{
return false;
}
void LinkedList::printForward() const
{
Node* temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
void LinkedList::printBackward() const
{
Node* temp = tail;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->prev;
}
cout << endl;
}
app.cpp
#include "list.h"
int main()
{
LinkedList aList;
aList.addAtBeginning(3);
aList.addAtBeginning(10);
aList.addAtBeginning(1);
aList.addAtBeginning(7);
aList.addAtBeginning(9);
aList.addAtBeginning(12);
aList.printForward();
aList.printBackward();
system("pause");
return 0;
}
I find it a bit odd that you only have an addAtBeginning method, and no method to add at the end, the latter which I would consider to be normal use of a linked list. That being said, I think the immediate problem here is that you never assign the tail to anything. Try this version of addAtBeginning:
bool LinkedList::addAtBeginning(int val)
{
Node* temp;
temp = new Node;
temp->data = val;
temp->next = head;
if (head != NULL)
{
head->prev = temp;
}
if (head == NULL)
{
tail = temp;
}
head = temp;
return false;
`}
The logic here is that for the first addition to an empty list, we assign the head and tail to the initial node. Then, in subsequent additions, we add a new element to the head of the list, and then assign both the next and prev pointers, to link the new node in both directions. This should allow you to iterate the list backwards, starting with the tail.
Update addAtBeginning function with given:
bool LinkedList::addAtBeginning(int val)
{
Node* temp;
temp = new Node;
temp->data = val;
temp->prev = temp->next = NULL;
// If adding first node, then head is NULL.
// Then, set Head and Tail to this new added node
if(head == NULL){
// If this linked list is circular
temp->next = temp->prev = temp;
head = tail = temp;
}else{ // If we already have at least one node in the list
// If this linked list is circular
temp->prev = head->prev;
temp->next = head;
head->prev = temp;
head = temp;
}
return false;
}
But remember, if you copy this function with the parts that it makes this list circular, you will get an infinite loop. So, either change print function or dont copy that parts.
When I run my program, it works as intended, except the items in the list have no spaces between them when the displayList() function is called. I have 3 files. The main cpp file is ShoppingList.cpp. Then I have two other files for the linked list classification and implementation.
//ShoppingList.cpp
//Michael Hery
//COP 2001
//11/9/17
//Shopping List
#include <iostream>
#include <string>
#include "strList.h"
#include "strlist.cpp"
using namespace std;
int main()
{
//Define a NumberList object
StrList list;
string item;
string delItem;
int menuSelection;
//Ask the user how many items to
//put in the list
cout << "How many items would you like to put it the list? >> ";
cin >> menuSelection;
while (menuSelection < 1)
{
cout << "Please enter a valid number (greater than 0) >> ";
cin >> menuSelection;
}
for (int i = 0; i < menuSelection; i++)
{
cout << "Please enter item " << i + 1 << ": ";
cin >> item;
list.appendNode(item);
}
list.displayList();
cout << "Which item do you wish to delete from the list? >> ";
cin >> delItem;
while (delItem == "")
{
cout << "Please enter a valid item >> ";
cin >> delItem;
}
list.deleteNode(delItem);
list.displayList();
//Wait for user input to exit program
system("PAUSE");
return 0;
}
//strList.h
#ifndef STRLIST_H
#define STRLIST_H
#include <iostream>
#include <string>
namespace
{
class StrList
{
private:
struct ListNode
{
std::string value;
struct ListNode *next;
};
ListNode *head;
public:
//Constructor
StrList()
{
head = nullptr;
}
//Destructor
~StrList();
//Linked List Operations
void appendNode(std::string item);
void insertNode(std::string item);
void deleteNode(std::string item);
void displayList() const;
};
}
#endif
//strList.cpp
#ifndef STRLIST_CPP
#define STRLIST_CPP
#include <iostream>
#include <string>
#include "strList.h"
void StrList::appendNode(std::string item)
{
ListNode *newNode;
ListNode *nodePtr;
//Allocate a new node and store item there
newNode = new ListNode;
newNode->value = item;
newNode->next = nullptr;
//If there are no nodes in the list
//make newNode the first node
if (!head)
head = newNode;
else //Otherwise, insert newNode at the end
{
//Initialize nodePtr to head of the 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 StrList::insertNode(std::string item)
{
ListNode *newNode;
ListNode *nodePtr;
ListNode *previousNode = nullptr;
//Allocate a new node and store num there
newNode = new ListNode;
newNode->value = item;
//If there are no nodes in the list
//make newNode the first node
if (!head)
{
head = newNode;
newNode->next = nullptr;
}
else //Otherwise, insert newNode
{
//Position nodePtr at the head of list
nodePtr = head;
//Initialize previousNode to nullPtr
previousNode = nullptr;
//Skip all nodes whose values is less than num
while (nodePtr != nullptr && nodePtr->value < item)
{
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
//If the new node is to be the 1st in the list,
//insert it before all the other nodes
if (previousNode == nullptr)
{
head = newNode;
newNode->next = nodePtr;
}
else //Otherwise insert after the previous node
{
previousNode->next = newNode;
newNode->next = nodePtr;
}
}
}
void StrList::deleteNode(std::string item)
{
ListNode *nodePtr; //To traverse the list
ListNode *previousNode = nullptr; //To point to the previous node
//If the list is empty, do nothing
if (!head)
return;
//Determine if the first node is the one
if (head->value == item)
{
nodePtr = head->next;
delete head;
head = nodePtr;
}
else
{
//Initialize nodePtr to head of list
nodePtr = head;
//Skip all nodes whose value member is
//not equal to num
while (nodePtr != nullptr && nodePtr->value != item)
{
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
//If nodePtr is not at the end of the list,
//link the previous node to the node after
//nodePtr, then delete nodePtr
if (nodePtr)
{
previousNode->next = nodePtr->next;
delete nodePtr;
}
}
}
StrList::~StrList()
{
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 != nullptr)
{
//Save a pointer to the next node
nextNode = nodePtr->next;
//Delete the current node
delete nodePtr;
//Position nodePtr at the next node
nodePtr = nextNode;
}
}
void StrList::displayList() const
{
ListNode *display;
display = head;
std::cout << "**********************************" << std::endl;
std::cout << "**** Your Shopping List ****" << std::endl;
std::cout << "**********************************" << std::endl;
while (display)
{
std::cout << display->value;
display = display->next;
}
}
#endif
The problem lies in the displayList(); function towards the end of the file.
Add a separator for between your values.
char const* sep = "";
while (display)
{
std::cout << sep << display->value;
sep = " ";
display = display->next;
}
I am a newbie to programming
Here I wrote a code for accepting and displaying the values using linked list.
However the code takes all the values but displays only the last value
Here is the code
#include <iostream>
using namespace std;
struct node {
int value;
node* next;
};
class llist {
public:
void create();
void display();
node* head = NULL;
};
void llist::create()
{
struct node* temp;
temp = NULL;
struct node* p;
p = new struct node;
cin >> p->value;
if (head == NULL) {
head = p;
}
else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->value = p->value;
temp->next = NULL;
}
}
void llist::display()
{
struct node* temp = head;
while (temp != NULL) {
cout << "VALUE:" << temp->value << endl;
temp = temp->next;
}
}
int main()
{
int n, i;
llist l1;
cin >> n;
for (i = 0; i < n; i++)
l1.create();
cout << "Displaying list\n";
l1.display();
return 0;
}
Input:
4
1
2
3
4
Displaying list
VALUE:4
I am wondering what went wrong...
Change this:
else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->value = p->value;
temp->next = NULL;
}
to this:
else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = p;
}
When inserting a new element at the end of a linked list, you find the last element inside the while loop and put it in the temp variable. Then you assign its next value to your new p element. The way you were doing before, you were just overriding the integer number of the last element. That is why when you printed your list you only got the last number you entered.
Also, when creating a new element p, be sure to initialize its next value to NULL:
p = new struct node;
p->next = NULL;
Problem is with the last 2 lines in the else block.
You are overwriting the value and maintaining just the single mode in your list class. And that's the reason, only last value is displayed.
Replace
temp->value = p->value;
temp->next = NULL;
With
temp->next = p;
I am trying to write a reverse print function as part of a doubly linked list. Here are the relevant functions that I have written:
void PLAYER::AddNode(int addID, std::string addName){
nodePtr n = new node; //creates a new node pointer
n->next = NULL; //Make next null
n->prev = NULL; // this will set this to be the ending node
n->ID = addID; //These two lines pass the information into the node
n->name = addName; // ID# and Name Information
if(head != NULL){ // This checks to see if a list is set up.
curr = head; // Make this point to the head.
while(curr->next != NULL){ // Loops through until the NULL is found
curr = curr->next;
}
curr->next = n; //Make the currnet node point to N
n->prev = curr; //Make the previous node connect to curr
n->next = tail; // connect new node to the tail.
}
else{
head = n; //If there is no list, this makes N the first node.
}
Here is the class that prototypes the functions to be used.
class PLAYER
{
public: // Functions go inside PUBLIC
PLAYER();
void AddNode(int addID, std::string addName);
void DeleteNode(int delPlayer);
void SortNode();
void PrintList();
void InsertHead(int AddID, std::string addName);
void PrintReverse();
private: //Variables go into here
typedef struct node{
// ...
std::string name;
int ID;
node* next;
node* prev;
}* nodePtr;
nodePtr head, curr, temp, prev, test, tail;
};
And finally my attempt to create a reverse traversing function to print backwards.
void PLAYER::PrintReverse()
{
curr = head;
while(curr->next != NULL) //Get to the end of the list
{
curr = curr->next;
}
while(curr->prev != NULL) //Work backward and print out the contents
{
std::cout << curr->ID << " " << curr->name << endl;
curr = curr->prev;
}
}
What I would like to do is inside the PrintReverse() function have it initialize via the tail pointer, however I can not figure out the functions to add to PrintReverse() and to AddNode() in order to have the new nodes pointed to by tail.
This is my first question posting here, I hope I covered all my bases. Thank you for any help I can find.
EDIT:
Thank you for all your input. I am relearning data structures and yes this is some self imposed homework on my part to begin to get the logic flowing again.
I will make the changes when I get home tonight.
The following changes would need to be considered.
The PrintReverse function would not need the forward pass to obtain the tail.
void PLAYER::PrintReverse()
{
curr = tail;
while(curr != NULL) //Work backward and print out the contents
{
std::cout << curr->ID << " " << curr->name << endl;
curr = curr->prev;
}
}
There is a problem in how tail is handled in the AddNode function. See the lines where the comments contain [CHANGED] and [ADDED]:
if(head != NULL){ // This checks to see if a list is set up.
curr = head; // Make this point to the head.
while(curr->next != NULL){ // Loops through until the NULL is found
curr = curr->next;
}
curr->next = n; //Make the currnet node point to N
n->prev = curr; //Make the previous node connect to curr
n->next = NULL; // [CHANGED]: we want the last node not to have a successor.
}
else{
head = n; //If there is no list, this makes N the first node.
}
tail = n; // [ADDED]: the last node added is the new tail.
However, a simpler solution is to avoid again the forward pass, and start from tail.
if(tail != NULL){ // This checks to see if a list is set up.
tail->next = n; //Make the old tail node point to N
n->prev = tail;
n->next = NULL;
}
else{
head = n; //If there is no list, this makes N the first node.
}
tail = n; // The last node added is the new tail.