Difficulties implementing sorted Doubly Linked list - c++

I'm taking a class in c++ and one of our assignments is to make an ADT for a linked list and do the implementations.
I've done well so far. But now I'm supposed to add the elements in order.
The code below is my ADD-function and what i've accomplished with this code is to sort them GIVEN that there are only 2 elements in the list. (I'm working with the problem from the basics, and refine my code after).
The while-loop on line 11 is my attempt to iterate (and int t are for debugging)
The problem i have is that my program crash without error (cmd stops working) if i try to add a number greater than 5.
The strange thing here is that if i remove my while-loop, it works. I can't find out whats wrong. So i hope for a little help
Main.cpp:
int main() {
SortedDoublyLinkedList<int> *list = new SortedDoublyLinkedList<int>(5, nullptr, nullptr);
int counter = 0;
while (counter < 2) {
int add;
cout << "Enter number: ";
cin >> add;
list->add(add);
counter++;
cout << counter << endl;
}
cout << list->removeLast()->getData()<< endl;
cout << list->removeLast()->getData()<< endl;
cout << list->removeLast()->getData()<< endl;
return 0;
}
SortedDoublyLinkedList.cpp
template<class T>
DoublyLinkedNode<T> *SortedDoublyLinkedList<T>::add(T val) {
if (isEmpty()) {
head = new DoublyLinkedNode<T>(val);
head->setPrevious(nullptr);
head->setNext(nullptr);
} else {
DoublyLinkedNode<T> *newEl = new DoublyLinkedNode<T>(val);
DoublyLinkedNode<T> *temp = head;
int t = 0;
while(temp->getData() != nullptr){
temp = temp->getNext();
t++;
cout << t << endl;
}
if(newEl->getData() > head->getData()){
newEl->setPrevious(head);
newEl->setNext(nullptr);
head->setNext(newEl);
cout <<"IF"<<endl;
}else{
DoublyLinkedNode<T> *temp = head;
head = newEl;
newEl->setPrevious(nullptr);
newEl->setNext(temp);
temp->setPrevious(head);
cout << "El" << endl;
}
}
numberOfElements++;
return head;
}

This bit of the loop (which I guess is trying to print out the items)... is wrong. The while part loops over the data while it works on elements
Your broken code :
while(temp->getData() != nullptr){
temp = temp->getNext();
t++;
cout << t << endl;
}
Somewhat more functional :
while(temp != nullptr){
cout << t << ":" << temp->getData() << endl;
temp = temp->getNext();
++t;
}
It doesn't solve your sorting problem, but as you said above, you are going iteratively, so I leave that for you to work out.

Related

Queue linked list not printing it's contents

I am trying to get input of a queue with the linked list implementation. The issue is that the contents of the queue aren't being printed. I tried debugging but it says that in the function displayCar that pointer p is null regardless. I can't tell what's wrong with why pointer p is NULL. Is there a missing reference when I am trying to push from the carInput function?
#include <iostream>
#include <queue>
using namespace std;
class record
{
public:
string ownerID, plateNumber;
record* next;
};
void push(string ownerID1, string plateNumber1, record **head, record **tail) {
record *n = new record();
n->ownerID = ownerID1;
n->plateNumber = plateNumber1;
n->next = NULL;
if (*head == NULL) {
*head =*tail= n;
}
else {
(*tail)->next = n;
*tail = n;
}
}
void pop(record** head, record** tail) {
record* p = *head;
while (*head != NULL) {
*head = (*head)->next;
free(p);
p = *head;
}
if (*head == NULL)
{
*tail = NULL;
}
}
void carInput(record *head, record *tail) {
char choice = 'Y';
string ownTemp, plateTemp;
while (choice == 'Y') {
cout << "Enter Owner Name: ";
cin >> ownTemp;
cout << "Enter Plate Number: ";
cin >> plateTemp;
push(ownTemp,plateTemp,&head,&tail);
cout << "Press [Y] for next input: ";
cin >> choice;
}
}
void displayCar(record* head, record *tail) {
record* p = head;
cout << "List Of Cars: \n";
int i = 1;
while (p!= NULL) {
cout << i << ". Owner Name: " << p->ownerID << endl;
cout << i << ". Plate Number: " << p->plateNumber<< endl;
pop(&head,&tail);
i++;
}
}
void serviceCar(record *head,record*tail) {
record* p = head;
string plateTemp;
int i = 0, time = 0;
char choice = 'Y';
cout << "Enter Plate Number:";
cin >> plateTemp;
while (p!= NULL) {
if (p->plateNumber == plateTemp) {
cout << "There is [" << i << "] car in queue before your turn. Estimated time in queue: " << time;
}
else {
i++;
time = time + 45;
}
pop(&head,&tail);
}
}
int main() {
record* head = NULL;
record*tail = NULL;
cout << ":: Car Record::\n\n";
carInput(head,tail);
displayCar(head,tail);
serviceCar(head, tail);
}
I don't know why you are punishing yourself with code like this when you are in C++ and there are plenty easier ways to do the same, but I'll try to help anyway by underlining the main problems:
1). The main reason that you must be struggling is that in the first push, even after *head =*tail= n;, the *head->next is still NULL and later when you'll try to iterate from the head, as you do in pop, *head = (*head)->next; you will get nothing.
2). if you want to do pop, you should delete one element for each call, not the whole collection - so you need if instead of while.
You have while where you using pop for each iteration and in the pop you also have the while, so think about it.
Also, you should be returning the value to display it easily - or change the way you trying to cout p in displayCar.
3). When you want to display the collection you just have to iterate through the collection instead of deleting all the elements, which will leave you empty collection after one display. You just need to iterate and display them, not to delete, something like that:
record* p = *head;
int i = 0;
while (p != NULL) {
cout << i << ". Owner Name: " << p->ownerID << endl;
cout << i << ". Plate Number: " << p->plateNumber<< endl;
p = p->next;
i++;
}
There are some other points that should be mentioned, but I think that's enough to get the code right direction - anyway, my advice would be to try to take a good look for simple linked-list how it's done and then try Queue linked-list, or just check already written examples and then try it by yourself. GeeksForGeeks
Your carInput receives pointers by value, and modifying those pointers has no effect on the pointers you pass to it.
Thus, main's head and tail are always null.
(You solved this with the pushing and popping functions, but failed to apply the same principle here.)
void carInput(record **head, record **tail) {
char choice = 'Y';
string owner, plate;
while (choice == 'Y') {
cout << "Enter Owner Name: ";
cin >> owner;
cout << "Enter Plate Number: ";
cin >> plate;
push(owner, plate, head, tail);
cout << "Press [Y] for next input: ";
cin >> choice;
}
}
You need to combine this fix with the fixes pointed out in the comments.

Print Index of a multilist

I am trying to print the index of a multi linked list. Each node has two elements- a warehouse number and a tool number. I am printing all the tools in each warehouse. I am having a problem with iterating correctly through the list.
I am not getting the correct values and am having trouble finding the problem in my method.
struct Node
{
int WarehouseNumber;
int ToolNumber;
struct Node *n;
}
void showWarehouses()
{
int tempvalue;
bool flag = false;
struct Node *s;
s = start;
if (start == NULL)
{
cout<<"Unable";
return;
}
s->WarehouseN = tempvalue;
cout<<"Warehouse "<<tempvalue<< ": Tool ";
while(s != NULL)
{
if (s->WarehouseN == tempvalue)
{
flag = true;
cout<< s->ToolN <<" ";
s = s->next;
}
}
}
You haven't assigned any values to tempvalue so it causes undefined behavior. Read this post.
Also based on what you have in struct Node and your code, I think you can have something like this picture in the program and you want to print them.
So to top it off I would write something like this code:
void showWarehouses()
{
int tempvalue=1;
bool flag, cont;
struct Node *s;
if (start == NULL)
{
cout << "Unable";
return;
}
cont = true;
while (cont)
{
cont = false, flag = false;
s = start;
while (s)
{
if (s->WarehouseN == tempvalue){
cont = true;
if (!flag){
cout << "Warehouse " << tempvalue << ": Tool ";
flag = true;
}
cout << s->ToolN << " ";
}
s = s->next;
}
cout << endl;
tempvalue++;
}
}
If this:
s = start;
struct Node *s;
compiles, you have an s in a wider scope that just got set to start before being hidden inside showWarehouses by another variable named s. That would be a bad thing.
Anyway, The immediate result is showWarehouses's s is never initialized and it's probably dumb unluck that the program doesn't crash. Since s is not initialized, the rest of the program is printing garbage so the output being wrong is to be expected.
i am assuming that ->warehouseN and ->toolN get the warehouse and tool nums accordingly. This is for right after your if statement.
struct Node *temp;
while (s != NULL){
temp = s;
cout << "Warehouse " << s->warehouseN << ": Tool ";
while (s!= NULL) {
cout << s->toolN << " ";
s = s-> next;
}
s = temp->next;
cout << endl;
}
also, you should probably initiate s before setting it as start

Segfault with initializing an int

/*Matt Boler
meb0054
hw5.cpp
Compile with gcc in cygwin
*/
#import <iostream>
#import <string>
#import <sstream>
#import <cstdlib>
#import <climits>
#import <assert.h>
using namespace std;
//#define UNIT_TESTING
struct TriviaNode
{
string question;
string answer;
int points;
TriviaNode *next;
};
typedef TriviaNode* NodePtr;
//Input: (1) root is the linked list to be added to
// (2) Question is the question for the node to ask
// (3) Answer is the answer to the node's question
// (4) Points is the point value of the node
//This adds a node to the end of the list
void appendNode(NodePtr& root, string question, string answer, int points);
//Input: (1) root is the linked list to get the length of
//Output: Returns the number of nodes in the linked list
//This calculates the number of nodes in a list
int getListLength(NodePtr& root);
//Input: (1) root is the node to start the list from
//This generates a hardcoded trivia list with 3 predefined questions and answers
void generateHardCodedList(NodePtr& root);
//Input: (1) root is the linked list containing questions to be asked
// (2) numQuestions is the number of questions to be asked from the list
//Output: returns o if answered correctly and 1 if answered incorrectly
//This asks the user a question
int askQuestion(NodePtr& root, int numQuestions);
int main()
{
#ifdef UNIT_TESTING
NodePtr head;
cout << "*** This is a debugging version ***" << endl;
cout << "Unit Test Case 1: Ask no questions. The program should give a warning" <<endl;
askQuestion(head, 0);
cout << "Test Case passed..." << endl;
generateHardCodedList(head);
cout << "Unit Test Case 2.1: Ask one question. The tester enters an incorrect answer" << endl;
assert(askQuestion(head, 1) == 1);
cout << "Test Case passed..." << endl;
cout << "Unit Test Case 2.2: Ask one question. The tester enters a correct answer" << endl;
assert(askQuestion(head, 1) == 0);
cout << "Test Case passed..." << endl;
cout << "Unit Test Case 3.1: Ask all questions. The tester enters incorreect answers" << endl;
assert(askQuestion(head, 1) == 1);
assert(askQuestion(head, 2) == 1);
assert(askQuestion(head, 3) == 1);
cout << "Test Case passed..." << endl;
cout << "Unit Test Case 3.2: Ask all questions. The tester enters correect answers" << endl;
assert(askQuestion(head, 1) == 0);
assert(askQuestion(head, 2) == 0);
assert(askQuestion(head, 3) == 0);
cout << "Test Case passed..." << endl;
cout << "Unit Test Case 4: Ask 5 questions in the linked list" << endl;
askQuestion(head, 5);
cout << "*** END OF THE DEBUGGING VERSION ***" << endl;
#else
{
cout << "Welcome to Matt Boler's Trivia Quiz Game!" << endl;
string userContinue = "";
string no = "No";
NodePtr head;
int numQuestions = 3;
generateHardCodedList(head);
while(userContinue.compare(no) != 0)
{
string question, answer;
int score;
cout << "Enter a question:";
getline(cin, question);
cout << "Enter an answer:";
getline(cin, answer);
cout << "Enter award points:";
cin >> score;
cin.clear();
cin.ignore(INT_MAX, '\n');
cout << "Continue? (Yes/No)" << endl;
getline(cin, userContinue);
numQuestions++;
}
//ANYTHING PAST HERE IN THE ELSE BLOCK FAILS VIA SEGFAULT OR JUST NOT RUNNING. NO IDEA WHY
int score = 0;
NodePtr cur = head;
for(int x = 1; x < numQuestions; x++)
{
cur = cur->next;
if(askQuestion(head, x) == 0)
{
score += cur-> points;
}
}
cout << "Your score is: " << score << endl;
}
#endif
return 0;
}
void appendNode(NodePtr& root, string q, string ans, int pts)
{
NodePtr cur;
NodePtr pre;
cur = new TriviaNode;
assert(cur != NULL);
cur->question = q;
cur->answer = ans;
cur->points = pts;
cur->next = NULL;
if (root == NULL)
root = cur;
else
{
pre = root;
while (pre->next != NULL)
{
pre = pre->next;
}
pre->next = cur;
}
}
void generateHardCodedList(NodePtr& root)
{
string q1 = "How long was the shortest war on record? (Hint: how many minutes)";
string ans1 = "38";
int pts1 = 100;
string q2 = "What was the Bank of America's original name? (Hint: Bank of Italy or Bank of Germany)";
string ans2 = "Bank of Italy";
int pts2 = 50;
string q3 = "What is the best-selling video game of all time? (Hint: Call of Duty or Wii Sports)";
string ans3 = "Wii Sports";
int pts3 = 20;
appendNode(root, q1, ans1, pts1);
appendNode(root, q2, ans2, pts2);
appendNode(root, q3, ans3, pts3);
}
int askQuestion(NodePtr& root, int numQuestions)
{
NodePtr cur;
cur = root;
if(numQuestions > getListLength(root))
{
cout << "Warning: there aren't that many questions in the list" << endl;
}
else if(numQuestions < 1)
{
cout << "Warning: the number of trivia to be asked must be greater than or equal to one" << endl;
}
else
{
for(int i = 1; i < numQuestions; i++)
{
cur = cur->next;
}
cout << "Question: " << cur->question << endl;
cout << "Player answer: ";
string player_answer;
getline(cin, player_answer);
cin.clear();
if (player_answer == cur->answer)
{
cout << "Your answer is correct. You recieve " << cur->points << " points." << endl;
return 0;
}
else
{
cout << "Your answer is wrong. The correct answer is: " << cur->answer << endl;
}
}
return 1;
}
int getListLength(NodePtr& root)
{
if(root == NULL)
{
return 0;
}
int count = 0;
NodePtr cur = root;
while(cur != NULL)
{
cur = cur->next;
++count;
}
return count;
}
This is a program to add trivia questions to a linked list in c++. Anything after the while loop causes an error. Specifically, initializing an int causes a segfault; trying to print to console with cout refuses to print anything out.
In the current version of the code your generateHardCodedList pases the root pointer to appendNode functions without initializing it. The calling code did not initialize root (called head in main), generateHardCodedList does not initialize it either, so appendNode receives a garbage pointer as root. After that all bets are off: your program is already broken.
I don't know why in your case it crashes so much later in the code, but it doesn't matter anyway. Your generateHardCodedList call is already broken.
Either initialize your head pointer with nullptr before passing it to generateHardCodedList, or better initialize it to nullptr inside generateHardCodedList, before trying to call appendNode.

Singly linked list , project stops working [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I am new to c++ , trying to write singly linked list in c++ , and it's various operations like , print, insert at the end, insert the end, delete etc. I am doing step by step. I have written my first insert method. It is working fine no error , but the first time it goes to the if condition of insert i.e the list is empty and create the first node here the problem is coming is after entering the first node the output screen is closing saying "project has stopped working" . what I am trying to do is after entering one node it should ask "do u wish to add another node?" if users enter "y" it should continue otherwise should go back to main function : Here is my code :
#include <iostream>
using namespace std;
struct node
{
int num;
node *next;
};
class link_list
{
node *head;
node *list;
public:
link_list()
{
head = NULL;
list = NULL;
//cout << list;
}
// void display_options(link_list &b);
void print_list();
void insert();
//void insert_at_beg();
// void insert_at_middle();
};
void link_list::print_list()
{
if (list == NULL)
{
cout << "Empty list" << endl;
//return;
}
else
{
int count = 0;
while (list->next != NULL)
{
list = list->next;
count++;
cout << "Node " << "value " << endl;
cout << count << " " << list->num << endl;
}
}
}
void link_list::insert()
{
// head = new node;
//list = head;
int y;
char a;
do
{
if (head == NULL)
{
head = new node;
cout << "enter the first node" << endl;
cin >> y;
list->num = y;
list->next = NULL;
}
else
{
node * newNode;
list == head;
while (list->next != NULL)
{
list->next = list;
}
newNode = new node;
cin >> y;
newNode->num = y;
list->next = newNode;
newNode->next = NULL;
}
cout << "do u wish to add another node?" << endl;
cin >> a;
} while (a == 'y' || a == 'Y');
}
int main()
{
link_list ll;
char choice;
do{
cout << "select one" << endl;
cout << "press 1 for insert ." << endl;
cout << "press 2 for insert at beginning ." << endl;
cout << "press 3 for insert at the middle ." << endl;
cout << "press 4 delete ." << endl;
cout << "print 5 print the linked list :" << endl;
cout << "print 6 exit :" << endl;
int no;
cin >> no;
switch (no)
{
case 1:
ll.insert();
break;
case 5:
ll.print_list();
case 6:
return 0;
default:
cout << "oops wrong choice" << endl;
}
fflush(stdin);
cout << "Do u wanna make another choice?" << endl;
cin >> choice;
cout << choice << endl;
} while (choice == 'Y' || choice == 'y');
cout << "Thanks!" << endl;
system("pause");
return 0;
}
You need to keep a more careful eye on your compiler warnings, and you need to learn how to use a debugger. There are many problems with this code, but most of them are easy to find by debugging.
This line in link_list::insert is not an assignment, it is a comparison. This would likely be raised as a compiler warning in most modern compilers. You'll probably want to fix that.
line == head
This loop doesn't do anything useful:
while (list->next != NULL)
{
list->next = list;
}
If list starts off as non-null, all this code will do is loop forever, repeatedly setting list->next to list. You probably wanted the operation to be the other way around.
list = list->next;
which will get you the last element in the list.
Still in the same function, this is broken:
head = new node;
cout << "enter the first node" << endl;
cin >> y;
list->num = y;
list->next = NULL;
because you haven't initialised list. Using head instead of list is probably what you wanted.
This is silly:
newNode = new node;
cin >> y;
because you don't prompt for the node value.
Once these changes are made, the code appears to function, at least for insertion and printing, but I'm not going to investigate further.
Perhaps this might be better moved to https://codereview.stackexchange.com/
head = new node;
cout << "enter the first node" << endl;
cin >> y;
list->num=y; //<-- problem
You are using list without initializing it. You should write
list = head;
before the statement list->num=y;
This will fix the bug for first time insertion. but there are several other problems in you code while inserting subsequently, which is pointed out by other answers. Modified code will be
void link_list::insert()
{
int y;
char a;
do
{
if (head == NULL)
{
head = new node;
cout << "enter the first node" << endl;
cin >> y;
head->num = y;
head->next = NULL; // no need to list as a member at all
}
else
{
node* list = head;
while (list->next != NULL)
{
list= list->next;
}
list->next= new node;
cin >> y;
list->next->num = y;
list->next->next = NULL;
}
cout << "do u wish to add another node?" << endl;
cin >> a;
} while (a == 'y' || a == 'Y');
}
void link_list::print_list()
{
if (head == NULL)
{
cout << "Empty list" << endl;
//return;
}
else
{
int count = 0;
node* list=head;
while (list->next != NULL)
{
count++;
cout << "Node " << "value " << endl;
cout << count << " " << list->num << endl;
list = list->next;
}
}
}

Pop method not giving expected output

I will show a portion of the program that is implementing my pop method for my stack below:
for (int i=0; i<10; i++) // pop 10 times
s1.Pop();
cout << "*pop 10 times\ns1=" << s1 << endl;
cout << "s1.Size()=" << s1.Size() << endl;
cout << "s1.IsEmpty()=" << ((s1.IsEmpty()) ? "T" : "F") << endl;
cout << "s1.IsFull()=" << ((s1.IsFull()) ? "T" : "F") << endl;
cout << "s1.Peek()=" << s1.Peek() << endl;
cout << endl;
Now I will show the pop method that this portion of code is using
T Pop()
{
Node* temp = top;
if(IsEmpty())
{
return NULL;
}
top = temp->link;
return temp->data;
num_items--;
}
The ouput I am getting is almost correct but some of it is off, i will show the output I am getting below:
I will now show the expected output:
To give more clarity, the max size of my list is 30, for some reason my num_items variable is not being decremented, i suspect i need a loop to check for something to decrement but i'm not sure what i should use. I've tried if(top != NULL){} //placing the rest of the code from Node* temp = top; to num_items--; into brackets
return temp->data;
num_items--;
num_items--; will never be executed as it comes after the return statement.
In T Pop():
return temp->data;
num_items--;
The second line will not be executed after you return.