Remove duplicates function doesnt work (C++ Linked Lists) - c++

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--;

Related

Bubble Sort Doubly Link List

I want to sort doubly link list using bubble sort. It is having loop problem and also the swap is not taking place properly.
The problem is the greatest number should be at the end after one iteration of i. But it doesn't and stop in between. I tried various options but could not solve it. Please help me solve this problem
#include <iostream>
using namespace std;
class node{
public:
node *next;
node *prev;
int data;
node(int x, node *p, node *n)
{
next = n;
prev = p;
data = x;
}
};
class list{
private:
node *head;
node *tail;
public:
list()
{
head = NULL;
tail = NULL;
}
void addtoend(int x)
{
if(head == NULL)
{
head = new node (x,NULL,NULL);
tail = head;
}
else if(tail->prev == NULL)
{
tail = new node(x,head,NULL);
head->next = tail;
}
else
{
node *temp = tail;
tail = new node(x,tail,NULL);
temp->next = tail;
}
}
void bubblesort()
{
node *temp = head;
node *temp2 = temp;
for(int i=0;i<10;i++)
{
cout<<"I: "<<i<<endl;
temp = head;
while(1)
{
temp2 = temp;
if(temp->next->data < temp->data)
{
if(temp == head)
{
cout<<"HEAD"<<endl;
head = head->next;
node *after = head->next;
head->prev = NULL;
temp->prev = head;
head->next = temp;
temp->next = after;
after->prev = temp;
}
else if(temp->next == tail)
{
cout<<"TAIL"<<endl;
node *back = temp->prev;
temp->next = NULL;
tail->next = temp;
temp->prev = tail;
back->next = tail;
tail->prev = back;
tail = tail->next;
tail->next=NULL;
}
else
{
cout<<"ANY"<<endl;
node *back = temp->prev;
node *after = temp->next->next;
back->next=temp->next;
temp->prev = temp->next;
after->prev->next = temp;
after->prev->prev = back;
after->prev = temp;
temp->next = after;
}
}
display();
display0();
temp = temp2->next;
cout<<"HEAD: "<<head->data<<endl;
cout<<"Tail: "<<tail->data<<endl;
cout<<endl;
if(temp->next->next== NULL)
{
break;
}
}
}
}
void display()
{
node *temp = head;
while(temp != NULL)
{
cout<<temp->data<<" ";
temp = temp->next;
}
cout<<endl;
}
void display0()
{
node *temp = tail;
while(temp != NULL)
{
cout<<temp->data<<" ";
temp = temp->prev;
}
cout<<endl;
}
};
main()
{
list l1;
int x[10] = {17,15,8,12,10,5,4,1,7,2};
for(int i=0;i<10;i++)
{
l1.addtoend(x[i]);
}
l1.display();
l1.bubblesort();
l1.display();
}
How-to implement bubblesort algorithm for double-linked list
There are at least two ways to implement the bubblesort algorithm in c++ for a double-linked list. Swapping the content aka the data of two neighbored nodes as shown under I. and re-wiring the pointers as shown under II.:
The advantage of II. is that no temporary memory temp2 is required. Therefore this is the preferred solution as stated also by the OP.
I. Swapping data
Just replace the OP bubblesort function by this one:
void bubblesort()
{
bool is_sorted = false;
node *temp = head;
while (!is_sorted)
{
is_sorted = true;
temp = head;
while (temp->next != NULL)
{
if(temp->next->data < temp->data)
{
is_sorted = false;
int temp2 = temp->data;
temp->data = temp->next->data;
temp->next->data = temp2;
}
temp = temp->next;
}
}
display();
display0();
}
The algorithm uses a Boolean variable is_sorted to check if the sorting of the double-linked list is finished. Otherwise the bubbles are still rising. It swaps only the data values of the double linked list.
II. Re-wiring the pointers
This is the required solution for the OP and the preferred one:
void bubblesort()
{
bool is_sorted = false;
node *temp = head;
while (!is_sorted)
{
is_sorted = true;
temp = head;
while (temp->next != NULL)
{
if(temp->next->data < temp->data)
{
is_sorted = false;
if(temp == head)
{
//temp->prev->next = temp->next; // 1. (impossible)
temp->next->prev = NULL; // 2.
head = temp->next;
}
else
{
temp->prev->next = temp->next; // 1.
temp->next->prev = temp->prev; // 2.
}
temp->prev = temp->next; // 3.
if(temp->next == tail)
{
temp->next = NULL; // 4.
tail = temp;
//temp->next->prev = temp2; // 5. (impossible)
}
else
{
temp->next = temp->next->next; // 4.
temp->next->prev = temp; // 5.
}
temp->prev->next = temp; // 6.
temp = temp->prev;
}
temp = temp->next;
}
}
display();
display0();
}
Output
The output of the program with updated bubblesort functions is:
17 15 8 12 10 5 4 1 7 2
1 2 4 5 7 8 10 12 15 17
17 15 12 10 8 7 5 4 2 1
1 2 4 5 7 8 10 12 15 17
First line shows the input list without sorting. The second shows the sorting result in ascending order, while the third shows the descending order, which proves that the forward and reverse links of the list are still working. The last line is the sorted list output in the main function.
The original order of the list is lost, of course.
The full source code is also available on github.
Hope it helps.
This is the code that I submitted and it is working properly. I find my mistakes by creating a visual picture on paper. Also my instructor has instructed to swap nodes, in any question data swapping is not acceptable.
void bubblesort()
{
node *temp = head;
int len = length();
for(int i=0;i<(len - 1);i++)
{
cout<<i<<endl;
temp = head;
int c=0;
while(c<(len - i - 1))
{
cout<<"Temp: "<<temp->data<<" ";
cout<<"Temp: "<<temp->next->data<<" "<<endl;
if(temp->next->data < temp->data)
{
if(temp == head)
{
cout<<"HEAD"<<endl;
head = head->next;
node *after = head->next;
head->prev = NULL;
temp->prev = head;
head->next = temp;
temp->next = after;
after->prev = temp;
temp = head->next;
}
else if(temp->next == tail)
{
cout<<"TAIL"<<endl;
node *back = temp->prev;
temp->next = NULL;
tail->next = temp;
temp->prev = tail;
back->next = tail;
tail->prev = back;
tail = tail->next;
tail->next=NULL;
temp= tail;
}
else
{
cout<<"ANY"<<endl;
node *back = temp->prev;
node *after = temp->next->next;
back->next=temp->next;
temp->prev = temp->next;
after->prev->next = temp;
after->prev->prev = back;
after->prev = temp;
temp->next = after;
temp = after->prev;
}
}
else
temp = temp->next;
display();
display0();
cout<<"HEAD: "<<head->data<<endl;
cout<<"Tail: "<<tail->data<<endl;
cout<<endl;
c++;
}
}
}

C++ linked lists deleting nodes

I am trying to go through a singly linked list and delete all nodes that contain a certain char. I have been trying to fix a pointer error (it said glibc detected: double free or corruption) by looking up online and trying those suggestions but now I seem to be stuck in a loop after rewriting my original code. I think the I am at least stuck in the 3rd while loop, I have tried using and if/else statement but the same thing happens. I also get a segmentation fault sometimes.
Code:
int MonsterList::removeMonsterType(char monster){
if(!isalpha(monster)) return 0;
if(first == 0) return 0;
int count = 0;
char key = toupper(monster);
MonsterNode *prev = first; //first is the ptr in the list this function is called on
if(prev->next == 0){
while(prev->id == key || prev->id == key+32){
first = 0;
delete prev; prev = 0;
count++;
return count;
}
return count;
}
MonsterNode *temp = prev->next;
while(temp != NULL){
while(prev->id == key || prev->id == key+32){
first = temp;
delete prev;
prev = temp;
temp = temp->next;
}
while(temp->id == key || temp->id == key+32){
prev->next = temp->next;
delete temp;
temp = prev->next;
count++;
}
prev = temp;
temp = temp->next;
}
return count;
}
Thanks in advance for your help.
No wonder you're having such trouble. You only need a single for loop. Allow me to simplify your code [please pardon some gratuitous style edits]. Note this is untested and may not be perfect:
int
MonsterList::removeMonsterType(char monster)
{
if (!isalpha(monster))
return 0;
// first is the ptr in the list this function is called on
if (first == 0)
return 0;
int count = 0;
char key = toupper(monster);
MonsterNode *prev;
MonsterNode *cur;
MonsterNode *next;
prev = NULL;
for (cur = first; cur != NULL; cur = next) {
// grab this _first_ so we have it before cur may be deleted (e.g. if
// cur gets deleted cur->next is immediately invalid, but this will
// remain)
next = cur->next;
if ((cur->id == key) || (cur->id == (key + 32))) {
// link previous item to next item
if (prev != NULL)
prev->next = next;
// replace first item in list
else
first = next;
// delete the node and advance the count
delete cur
count++;
continue;
}
// remember previous item
prev = cur;
}
return count;
}

Linked list not working for input

I'm writing code that takes integers that are input from the user and creates a linked list and then prints out the list. However, when I enter values 1,2,3,4,5, the output is only 5 5 5 5 5
Please tell me where am i wrong here.
The code is as follows:
include"iostream"
using namespace std;
struct node
{
int number;
node* next;
};
int main()
{
node* head;
head = NULL;
int i,n,x;
cin>>n;
cout<<endl;
for(i=0;i<n;i++)
{
cin>>x;
//Insert(x);
node* temp;
temp = new node;
temp->number = x;
temp->next = NULL;
head = temp;
}
//Print();
node* temp;
temp = head;
while(temp != NULL)
{
for(int j=0; j<n; j++)
cout<<temp->number<<" ";
temp = temp->next;
}
}
Remember that when setting the head pointer, you should only do so when the list is empty (i.e when head == NULL). We should do this after we create the new node so we know what to set head to:
node* temp = new node;
temp->number = x;
temp->next = NULL;
if (head == NULL) // if the list is empty then...
head = temp; // temp is the start of the list
There's also another problem. temp is supposed to be added to the end of the list each time it's created. If the list is empty then head is the end of the list, but if the list already has elements then we need to go to the end and set the next pointer of that node to temp. This is fairly straightforward, all it takes is a while loop to iterate over the list to the end:
if (head == NULL)
head = temp;
else // the list is not empty
{
// so we need to go to the end
node* p = head;
while (p->next != NULL)
p = p->next; // keep going through
// p now points to the last node
p->next = temp;
}
There's also the option of keeping a prev node that points to the last element inserted. This makes it so that we don't have to go through the list each time to find the end:
node* head = NULL, prev = NULL;
for (/* ... */)
{
// ...
if (head == NULL)
head = prev = temp;
else
{
prev->next = temp;
prev = temp;
}
}
The last thing is the way you're printing. You shouldn't have a nested for loop here:
while (temp != NULL)
{
for(int j = 0; j < n; j++)
cout << temp->number << " ";
temp = temp->next;
}
Taking it out will make it print correctly.
This looks a bit wrong:
while(temp != NULL)
{
for(int j=0; j<n; j++)
cout<<temp->number<<" "; // Only this is part of the for() loop
temp = temp->next; // This happens after the for() loop ends
}
Only the first line gets executed by the for() loop so it keeps outputting the same number. Why is the for loop there anyway? What is it supposed to do?
Try this:
while(temp != NULL)
{
cout<<temp->number<<" ";
temp = temp->next;
}
See if that works better.
ALSO:
As #crashmstr pointed out your insert logic is wrong:
for(i=0;i<n;i++)
{
cin>>x;
//Insert(x);
node* temp;
temp = new node;
temp->number = x;
temp->next = NULL; // this should point to the nextnode
head = temp;
}
Try:
for(i=0;i<n;i++)
{
cin>>x;
//Insert(x);
node* temp;
temp = new node;
temp->number = x;
temp->next = head; // the current begining
head = temp;
}
*ALSO 2:
include"iostream" // not right
Please use:
#include <iostream> // correct!

How to solve error in code and interpret error message

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;
}

Sorting a Singly Linked List With Pointers

I am trying to sort a singly linked list using bubble sort by manipulating ONLY the pointers, no keys.
The following gets stuck in the for loop and loops infinitely. I don't understand why this is. Can anybody explain to me why the end of the list is not being found?
Node* sort_list(Node* head)
{
Node * temp;
Node * curr;
for(bool didSwap = true; didSwap; ) {
didSwap = false;
for(curr = head; curr->next != NULL; curr = curr->next) {
if(curr->key > curr->next->key) {
temp = curr;
curr = curr->next;
curr->next = temp;
didSwap = true;
}
cout << curr->next->key << endl;
}
}
return head;
}
If I change the code so that the keys (data) are swapped, then the function works properly but for some reason I am not able make it work by manipulating only pointers.
Logical Error, you are creating an infinite loop with following code -
temp = curr;
curr = curr->next;
curr->next = temp;
I,e next_of_current is pointing to current, so curr->next will always be curr and never will be NULL;
Next you should use previous pointer to fix your list because your list can be traversed in a single direction. So, Think -
If A->B->C->NULL; and you make C and B swap then the new list will still point to A->B and next iteration will be wrong ... because you are not modifying your previous next.
So, another implementation may be -
Node* sort_list(Node* head) {
Node * curr;
Node * prev;
for(bool didSwap = true; didSwap; ) {
didSwap = false;
prev = head;
for(curr = head; curr->next != NULL; curr = curr->next) {
if(curr->key > curr->next->key) {
if (head == curr) {
head = curr->next;
curr->next = head->next;
head->next = curr;
prev = head;
} else {
prev->next = curr->next;
curr->next = prev->next->next;
prev->next->next = curr
}
didSwap = true;
} else if (head != curr) {
prev = prev->next;
}
//cout << curr->next->key << endl; // <- this may cause crash if curr->next now points to NULL; (i,e last element)
}
}
return head;
}
Hope this helps, regards.
You have following problem:
Let you have list with three members: ptr1->ptr2->ptr3. Before swap you have following pointer set: curr=ptr1; curr->next=ptr2; curr->next->next=ptr3. When you perform swap you receive curr=ptr2; curr->next=ptr1; curr->next->next=ptr2.
E.g. you lost ptr3. You need to change code of inner loop with following:
temp = curr;
temp->next = curr->next->next; // Save ptr3
curr = curr->next;
curr->next = temp;
didSwap = true;
The field you want to swap is the value. However, if you swap the node, the next field will change, the question becomes a little more complex, you need keep the next field right. In a word, change value is a simple and good method.
node *sorted_list(node *head) {
node *index1,*index2;
for(index1=head;index1->next!=NULL;index1=index1->next) {
for(index2=index1->next;index2!=NULL;index2=index2->next) {
if(index1->data>index2->data) {
int temp=index1->data;
index1->data=index2->data;
index2->data=temp;
}
}
}
return head;
}