So I'm working on a project using linked lists. The program basically takes in numbers until -999 is inputted and then does operations on it. The two operations I am having problems with are deleteAll, where all the same values are deleted from the list, and deleteSmallest, where the smallest value in the list is deleted. The code that calls both functions is as follows:
int num;
cout << "Enter a number you would like deleted from the whole list: ";
cin >> num;
uList.deleteAll(num);
cout << "New list: " << uList << endl;
uList.deleteSmallest();
cout << "After deleting the smallest number, the list now is: " << uList << endl;
The code for deleteAll is as follows:
template <class Type>
void UnorderedLinkedList<Type>::deleteAll(const Type& deleteItem)
{
NodeType<Type>* curr;
NodeType<Type>* p = NULL;
NodeType<Type>* q = NULL;
curr = first;
if(first == NULL)
throw std::runtime_error("Cannot delete from an empty list");
else
{
for(int i = 0; i < count; i++)
{
if(curr->info == deleteItem)
{
p = curr;
q = p->link;
p->link = q->link;
delete q;
}
curr = curr->link;
}
}
delete p;
delete curr;
}
The code for deleteSmallest is as follows:
template <class Type>
void UnorderedLinkedList<Type>::deleteSmallest()
{
NodeType<Type>* curr;
NodeType<Type>* p;
NodeType<Type>* q;
NodeType<Type>* r;
curr = first;
if (first == NULL)
throw std::runtime_error("Cannot delete from an empty list");
else
{
for(int i = 0; i < count; i++)
{
if(curr->link->info < curr->info)
{
int smallest = curr->link->info;
p = curr;
q = curr->link;
}
curr = curr->link;
}
}
r = q->link;
p->link = q->link;
delete q;
}
The error that I get is:
1 [main] Project 5 4044 cygwin_exception::open_stackdumpfile: Dumping stack trace to Project 5.exe.stackdump
Sorry to post a large question, but can someone explain what the error means in this situation and what I'm doing that is causing this to come up? Thank you!
For deleteAll() you should be doing something like this:
else
{
for (Node* prev = curr; curr != NULL; prev = curr, curr = curr->link)
{
if (curr->info == deleteItem)
{
NodeType<Type>* temp = curr;
curr = curr->link;
if (prev)
prev->next = curr;
delete temp;
}
}
}
The way you had it before was not deleting curr at all. You should also remove the delete p and delete curr at the bottom as they are redundant.
And for deleteSmallest(), you need to keep a pointer pointing to the smallest node (and a previous node pointing to the one before it) so when the loop finishes you know what delete:
else
{
Node* prev = NULL, **smallest;
for (Node** curr = smallest = head, *back(*head); *curr != NULL; back = *curr, curr = &(*curr)->link)
{
if ((*curr)->info < (*smallest)->info)
{
prev = back;
smallest = curr;
}
}
Node* temp = *smallest;
*smallest = (*smallest)->link;
if (prev)
prev->link = *smallest;
delete temp;
}
Related
I'm trying to make single linked list's fucntions.
but it reports an error. like this..
i am trying to a lot of thing about that.
like using rvlaue reference, double pointer
but nothings work..
what is the problem?
and can i return p pointer in getNode(int k) fucntion?
#include<iostream>
using namespace std;
template<typename T>
class SingleLList {
private:
template<typename T>
struct Node {
T data;
Node<T>* next;
};
Node<T>* head;
int size; // for List size
public:
SingleLList() :head(nullptr) {};
~SingleLList() {
Node<T>* delNode;
while (head->next != nullptr) {
delNode = head;
head = head->next;
delete delNode;
}
};
// add Node at index th
void addNode(int index, T data) {
if (index < 0)return;
Node<T>* newNode = new Node<T>;
newNode->data = data;
newNode->next = nullptr;
if (index == 0) { // add at 0
// empty
if (head == nullptr) head = newNode;
// not empty
else {
newNode->next = head->next;
head = newNode;
}
size++;
}
else {
Node<T>* prev = head;
for (int i = 1; i < index && prev != nullptr; i++) {
prev = prev->next;
}
newNode->next = prev->next;
prev->next = newNode;
size++;
}
}
// traversa
void showList()const {
Node<T>* p = head;
cout << "Single Linked List : [ ";
while (p != nullptr) {
cout << p->data << " ";
p = p->next;
}
cout << " ]" << "total elements are : "
<< size << endl;
}
// return k th Node by reference.
Node<T>*& getNode(int k)const {
if (head == nullptr || k > size) {
Node<T>* temp = nullptr;
return temp;
}
// Node<T>* p; < -- is it okay?
Node<T>* p = new Node<T>;
p= head;
for (int i = 1; i < k && p->next != nullptr; i++) {
p = p->next;
}
cout << " address of p : " << &p << endl;
cout << "value of p : " << p << endl;
return p;
}
// delete n Node in list
void deleteNode(Node<T>*& n) {
cout << "address of n : " << &n << endl;
cout << n->data << endl;
if (n->next == nullptr) { // if last node
delete n->next;
n = nullptr; //
size--;
}
else {
Node<T>* del_node = n->next;
n->data = n->next->data;
n->next = n->next->next;
delete del_node;
size--;
}
}
};
int main() {
SingleLList<int> sll;
sll.addNode(0, 4);
sll.addNode(1, 5);
sll.addNode(2, 6);
sll.addNode(3, 8);
sll.addNode(4, 9);
sll.showList();
sll.deleteNode(sll.getNode(5));
sll.showList();
return 0;
}
and in main i make Linked List like this.
Node<T>*& getNode(int k)const {
if (head == nullptr || k > size) {
Node<T>* temp = nullptr;
return temp;
This same basic bug occurs several times in the shown code. All instances of this bug will need to be fixed.
temp is a local variable. Once this function returns, it goes out of scope and gets destroyed.
However: this function is declared as returning a reference to a pointer, and by returning temp this ends up returning a reference to an object that's already destroyed, when the function returns. All subsequent use of this reference automatically becomes undefined behavior, and the likely reason for your crash. For example:
sll.deleteNode(sll.getNode(5));
For example, getNode() returns a reference here. To add insult to injury this reference isn't even used immediately, but it gets passed to deleteNode(). By that time temp, or a reference to whatever was originally returned from getNode, is a distant memory and was already destroyed a long, long time ago, and attempting to reference it will not end well.
There are likely other issues, but this is fundamental, and fixing it will require fundamental changes to the shown logic, as such the first order of business will be to redesign the shown code, and it will likely involve other major changes to the rest of the code, as well.
I've been trying to write a function for an assignment that removes duplicate entries in a linked list but it just doesnt work no matter what I try. It either does nothing or crashes.
displayList works fine on its own so it's not the problem here.
void List::delNode(int pos){
if(isEmpty()){
cout<<"The list is empty."<<endl;
return;
}else{
Student* temp;
temp = head;
curr = temp->next;
if(pos == 0){
head = curr;
delete temp;
}else{
for(int i = 1; i<pos-1; i++){
curr = curr->next;
temp = temp->next;
}
temp->next = curr->next;
delete curr;
}
}
}
void List::removeDuplicate(List &l){
float gpa;
bool flag = false;
string name;
Student *copy, *temp;
curr = head;
for(int i = 0; curr != NULL; i++){
cout<<"pass "<<i<<endl;
copy = curr;
temp = curr->next;
gpa = curr->S_gpa;
name = curr->S_name;
for(int e = i; temp != NULL; e++){
flag = false;
if(temp->S_gpa == gpa && temp->S_name == name){
copy->next = temp->next;
l.delNode(e);
copy = curr;
temp = curr->next;
flag = true;
e = i;
}
if(flag){
}else{
//copy = copy->next;
temp = temp->next;
}
}
curr = curr->next;
}
displayList();
}
List::delNode(int pos) on its own looks OK. Except curr should be a local variable, like temp is.
List::removeDuplicate(List &l) accepts a list to remove from, but loops and checks its own elements. Either use List &l for all data, or none.
In List::removeDuplicate(List &l), the curr should probably also be a local variable.
When you have found a duplicate, you just want to move to the next node, then delete the current node. Deleting the current node, changes the index of the next node, so correct for that by decreasing e:
temp = temp->next;
delNode(e);
e--;
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;
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm trying to review data structures and implement a basic linked list. When I run this code, I get the following output:
3 4 6
1 was found and deleted 4 was found and deleted
3
4 should be deleted, but obviously 1 should not, and I'm wondering where the error in my code/logic is.
Thanks in advance for any help.
#include <iostream>
using namespace std;
class List {
private:
struct node {
int data;
node * next;
};
node * head;
node * curr;
node * temp;
public:
List();
void addNode(int newData);
void deleteNode(int delData);
void printList();
};
int main() {
List test;
test.addNode(3);
test.addNode(4);
test.addNode(6);
test.printList();
cout << endl << endl;
test.deleteNode(1);
test.deleteNode(4);
cout << endl << endl;
test.printList();
}
List::List(){
head = NULL;
curr = NULL;
temp = NULL;
}
void List::addNode(int newData){
node * n = new node;
n->next = NULL;
n->data = newData;
if (head != NULL) { // List is intact
curr = head; // if List is not empty, make curr equal to the head, and start at the beginning of the list.
while(curr->next != NULL) { // Get to last item on the list
curr = curr->next;
}
curr->next = n; // Use the last item, and point to the new node.
}
else { // empty list
head = n; // new node is the head of the list.
}
}
void List::deleteNode(int delData){
node * n = new node;
temp = head;
curr = head;
if (head != NULL) {
while (curr->next != NULL && curr->data != delData) {
temp = curr;
curr = curr->next;
}
if (curr == NULL) {
cout << delData << " was not found in the list\n";
delete n;
}
else {
n = curr;
curr = curr->next;
temp->next = curr;
delete n;
cout << delData << " was found and deleted\n";
}
}
}
void List::printList(){
curr = head;
while (curr != NULL) {
cout << curr->data << endl;
curr = curr->next;
}
}
The following line allocates a new node.
node * n = new node;
As already pointed out in the comments, it is not clear why the deleteNode() is doing that. The subsequent lines of delete n is actually deleting this new node, not one of the nodes in the list.
I would try writing deleteNode() something like this:
void List::deleteNode(int delData) {
// Empty list
if (!head) return;
// The first node is to be deleted
if (head->data == delData) {
node * old_head = head;
head = head->next;
delete old_head;
return;
}
// A non-first node is to be deleted
for (node * cur = head; cur; cur = cur->next) {
if (cur->next && cur->next->data == delData) {
node * del_node = cur->next;
cur->next = cur->next->next;
delete del_node;
break;
}
}
}
Actually the problem in your code was that the condition :
curr-> next !=NULL had to be replaced by curr!= NULL
since the code stops one step before it requires to stop.
Here is your working code:
#include <iostream>
using namespace std;
class List {
private:
struct node {
int data;
node * next;
};
node * head;
node * curr;
node * temp;
public:
List();
void addNode(int newData);
void deleteNode(int delData);
void printList();
};
int main() {
List test;
test.addNode(3);
test.addNode(4);
test.addNode(6);
test.printList();
cout << endl << endl;
test.deleteNode(1);
test.deleteNode(4);
cout << endl << endl;
test.printList();
}
List::List(){
head = NULL;
curr = NULL;
temp = NULL;
}
void List::addNode(int newData){
node * n = new node;
n->next = NULL;
n->data = newData;
if (head != NULL) { // List is intact
curr = head; // if List is not empty, make curr equal to the head, and start at the beginning of the list.
while(curr->next != NULL) { // Get to last item on the list
curr = curr->next;
}
curr->next = n; // Use the last item, and point to the new node.
}
else { // empty list
head = n; // new node is the head of the list.
}
}
void List::deleteNode(int delData){
node * n = new node;
temp = head;
curr = head;
if (head != NULL) {
while (curr!= NULL && curr->data != delData) {
temp = curr;
curr = curr->next;
}
cout<<temp->data<<" ";
if (temp->next == NULL) {
cout << delData << " was not found in the list\n";
delete n;
}
else {
n = curr;
curr = curr->next;
temp->next = curr;
delete n;
cout << delData << " was found and deleted\n";
}
}
}
void List::printList(){
curr = head;
while (curr != NULL) {
cout << curr->data << endl;
curr = curr->next;
}
}
As #drescherjm said, that extra allocation could be skipped.
The final deletenode function is:
void List::deleteNode(int delData){
node * n ;
temp = head;
curr = head;
if (head != NULL) {
while (curr!= NULL && curr->data != delData) {
temp = curr;
curr = curr->next;
}
cout<<temp->data<<" ";
if (temp->next == NULL) {
cout << delData << " was not found in the list\n";
// delete n;
}
else {
n = curr;
curr = curr->next;
temp->next = curr;
delete n;
cout << delData << " was found and deleted\n";
}
}
}
That may seem kind of vague so really sorry. I am writing to a file and printing to a console the sorted nodes in this singly linked list. Unfortunately, in the sort list, it both prints and writes an extra 0 at the front and cuts a value off the end. Here is the code:
void SLLIntStorage::Read(istream& r)
{
char c[13];
r >> c;
r >> numberOfInts;
head = new Node;
head->next = NULL;
tail = head;
r >> head->data;
for (int i = 0; i < numberOfInts; i++)
{
Node* newNode = new Node;
r >> newNode->data;
if(_sortRead)
{
if(newNode->data > tail->data)
{
tail->next = newNode;
tail = newNode;
}
else if(head->data > newNode->data)
{
newNode->next = head;
head = newNode;
}
else
{
current = head;
while(current->next != NULL)
{
if(current->next->data > newNode->data)
{
newNode->next = current->next;
current->next = newNode;
break;
}
else
{
current = current->next;
}
}
}
}
else
{
tail->next = newNode;
tail = newNode;
}
}
print();
}
void SLLIntStorage::Write(ostream& w)
{
current = head;
for(int i = 0; i < numberOfInts; i++)
{
w << current->data << endl;
if (current->next != NULL)
current = current->next;
}
}
void SLLIntStorage::print()
{
current = head;
for(int i = 0; i < numberOfInts; i++)
{
cout << current->data << endl;
//system("pause");
if(current->next != NULL)
{
current = current->next;
}
}
}
File sample:
0
0
1
2
2
3
........
9995
9996
9996
9998
//supposed to be another 9998 here
It seems you read one entry too much. You first read an entry in the line r >> head->data;
just before the for-loop. Then you read an additional numberOfInts entries in the for-loop for a total of numberOfInts+1 entries.