Removing a node in a circular doubly linked list - c++

I'm trying to write some code to remove a node from a circular doubly linked list. I've written the following function, which mostly works:
bool Circular::remove(int index)
{
if (head == NULL)
return false;
Node* current;
current = head;
if (index > 0)
{
for (int i = 0; i < index; i++)
{
current = current->next;
}
}
else if (index < 0)
{
for (int i = 0; i < abs(index); i++)
{
current = current->prev;
}
}
if (current == head)
{
head = current->next;
}
else if (current == tail)
{
tail = current->prev;
}
current->prev->next = current->next;
current->next->prev = current->prev;
return true;
}
The only problem I have is that it won't remove the correct value when I pass the number 1 into the index number. Instead it always deletes the tail. If you think there's something wrong with my code somewhere else then I'll also look into it.

I think I've figured it out. Mostly I used functions to remove the head...
Node* temp = head;
head = head->next;
head->prev = tail;
tail->next = head;
delete temp;
return true;
...and to remove the tail:
Node* temp = tail;
tail = tail->prev;
tail->next = head;
head->prev = tail;
delete temp;
return true;
Apparently just moving around the head and tail wasn't enough to actually delete those nodes.

Related

Deleting a key from a circular linked list

void deletenode(string key) {
if (last == NULL) {
cout << "your circular linked list is an empty one" << endl;
}
else {
node* p = last->next;
node* prev = last;
do {
if (p->title == key) {
node* temp = p;
prev->next = p->next;
delete(temp);
}
else {
p = p->next;
prev = prev->next;
}
} while (p != last->next);
}}
I was trying to delete a node with key value. For instance, if node p->title is my key then I want to delete that node. However, I implemented it with other values but the code doesn't seem to work or delete a node with key value from my circular linked list. What is the mistake in the function?
circular linked list value "cat", "dog", "rat", "horse", the key to be deleted was "dog". When I traverse throughout the linked list after the deletion it still printed everything including "dog", which means deletion didn't work.
Anytime you write a "delete from the linked list" function, you have to account for the possibility that you are deleting from the "head" or whatever pointer you are referencing with the list. The common pattern is for the function to return the new head of the list if it changed, else return the current head.
Node* deletenode(Node* head, const string& key) {
// empty list
if (head == nullptr) {
return nullptr;
}
// single item list
if (head->next == nullptr || head->next == head) {
if (head->title == key) {
delete head;
head = nullptr;
}
return head;
}
// two or more item list, possibly circular
Node* prev = head;
Node* current = head->next;
Node* first = current;
while (current && current->title != key) {
prev = current;
current = current->next;
if (current == first) {
break;
}
}
if (current == nullptr || current->title != key) {
return head; // not found
}
prev->next = current->next;
if (current == head) {
head = current->next;
}
delete current;
return head;
}
I don't see the full code so I can't make a comment I tried to implement the function, hope it helps you with the comments.
void deleteNodeWithKey(node* head, string key)
{
node *curr = head;
node *last , *temp;
//Search for last node
while (curr->next != head)
{
curr = curr->next;
}
last = curr;
//If head is the desired key, make head's next new head
//and connect last node to new head
if (head->key == key)
{
temp = head->next;
delete head;
head = temp;
last->next = head;
return;
}
temp = head->next;
//Search for node with the given key
node *prev = head;
while (temp != head)
{
if (temp->key == key)
{
prev->next = temp->next;
delete temp;
return;
}
temp = temp->next;
prev = prev->next;
}
//If function gets here, key was not found
}
I made some changes to your code
void deletenode(string key) {
if (last == NULL) {
cout << "your circular linked list is an empty one" << endl;
}
else {
node* prev = last;
// If head is to be deleted
if (last->title == key) {
while (prev->next != last)
prev = (prev)->next;
prev->next = last->next;
free(last);
last = prev->next;
return;
}
node* p = last->next;
do {
if (p->next->title == key) {
node* temp = p->next;
p->next = temp->next;
delete(temp);
}
else {
p = p->next;
prev = prev->next;
}
} while (p != last->next);
}
}

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

How can I change this insert function to work in a linked list using strings?

This is the first question that I'm posting on StackOverflow, so forgive me if it seems kinda choppy.
For my computer science class, we're working with a double linked list for the current assignment. One of the functions required is an insert function.
I actually found an insert function on StackOverflow earlier this week, but it was set up to use structures inside of the main file instead of separate class files like this project is using. I think the function can work, but I'm not sure what alterations I need to make so that it can work with class files instead.
LinkedList.h member data
private:
Node *head, *tail;
mutable Node *it;
int count;
Insert function
bool LinkedList::insert(const string & str) const
{
LinkedList * tempVar;
if (hasMore) {
resetIterator();
}
else {
Node * temp = new Node;
//temp = str;
temp->data = str;
temp->next = it;
temp->prev = nullptr;
it->prev = temp;
it = temp;
}
if (it != nullptr) {
Node * current = it;
Node * previous = nullptr;
Node * tempNode = nullptr;
while (current->next != nullptr) {
tempNode = current->next;
if (current->data > tempNode->data) {
swap(current->data, tempNode->data);
}
else {
previous = current;
current = current->next;
}
}
tempVar->count += 1;
}
return false;
}
I haven't been able to test it yet due to not knowing what alterations are needed, but the function should insert strings that are passed into the argument into the linked list, as well as sort them in a dictionary style. Right now the only error is that temp = str; not working, and I'm not entirely sure what I need to do to get it to work.
Try something more like this:
bool LinkedList::insert(const string & str)
{
Node * current = head;
while ((current) && (current->data < str))
current = current->next;
Node *newNode = new Node;
newNode->data = str;
newNode->next = nullptr;
newNode->prev = nullptr;
if (current)
{
if (current->previous)
{
current->previous->next = newNode;
newNode->previous = current->previous;
}
current->previous = newNode;
newNode->next = current;
if (current == head)
head = newNode;
}
else
{
if (!head)
head = newNode;
if (tail)
{
tail->next = newNode;
newNode->previous = tail;
}
tail = newNode;
}
count += 1;
return true;
}
That being said, you really should be using the standard std::list container instead of implementing a double-linked list manually.

c++ linked list, insert strings

This is my homework: Create a linked list class which stores a list of unique (no duplicates allowed) strings in alphabetic order.
enter image description here
and this is what I have so far, which is not working. can anyone find the problems for me? thank you very much. the error looks like this:
+ std::_String_alloc<std::_String_base_types<char,std::allocator<char> > > {_Mypair={_Myval2={_Bx={_Buf=0x0135f988 "Adam" _Ptr=0x6d616441 <Error reading characters of string.> ...} ...} } } std::_String_alloc<std::_String_base_types<char,std::allocator<char> > >
my code:
bool LinkedList::insert(string dataInsert) {
//remember to use find funcion to check dupcated.
if (find(dataInsert) != 0)
return false;
// build new node.
Node* newNode = new Node;
newNode->data = dataInsert;
newNode->next = NULL;
//insert into empty list
if (head == NULL)
{
head = newNode;
return true;
}
//insert before first item
if (newNode->data < head->data)
{
newNode->next = head;
head = newNode;
return true;
}
//insert somewhere after first item
Node* previous = head;
while (previous->next != NULL && previous->next->data < newNode->data)
{
previous = previous->next;
newNode->next = previous->next;
previous->next = newNode;
return true;
}
}
Your below while might have some problems because newNode was inserted every time when you found the next node has smaller data than newNode.
while (previous->next != NULL && previous->next->data < newNode->data)
{
previous = previous->next;
newNode->next = previous->next;
previous->next = newNode;
return true;
}
I think your solution is finding a position of the largest node that smaller than newNode. You can refer below code:
while (previous->next != NULL && previous->next->data < newNode->data)
{
previous = previous->next;
}
newNode->next = previous->next;
previous->next = newNode;
return true;

Insert Function on Doubly Linked List

So I've got this insert function for a doubly linked list that is working for the most part just up until I try to insert a new node at a given index. I'm having trouble with linking it correctly to the nodes before and after it, if anyone could see why, I keep getting errors when I try to assign one of the points I'll point out in the code:
void insert(int index, ItemType& item)
{
int pos = 0;
Node* current = new Node;
Node* n = new Node;
n->info = item;
if (index >= 0 && index <= size)
{
if (size == 0)
{
head = n;
tail = n;
n->next = NULL;
n->prev = NULL;
size++;
return;
}
else if (index == 0)
{
n->prev = NULL;
n->next = head;
head->prev = n;
head = n;
size++;
return;
}
else if (index == size)
{
n->next = NULL;
n->prev = tail;
tail->next = n;
tail = n;
size++;
return;
}
else if (index < size/2)
{
current = head;
while(pos != index)
{
current = current->next;
pos++;
}
}
else if (index > size/2)
{
int endpos = size - 1;
current = tail;
while(endpos != index)
{
current = current->prev;
endpos--;
}
}
n->next = current;
current->prev->next = n; // HERE is where the code breaks, don't know why.
n->prev = current->prev;
current->prev = n;
size++;
}
}
So the code breaks at the current->prev->next = n statement stating there is an access violation writing location. So I'm not sure if that is coded right or if I've messed up in pointing assignments in earlier code. If anyone knows why its doing that and can point me in the right direction that would be awesome. Thanks.
From my observation,
Your code fails when index = size/2.
When there are two elements(size == 2) and when you try to insert at position 1, then current->prev->next = n; is meaningless
Do one of these changes else if (index <= size/2) or else if (index >= size/2)
If current is the first node in the list, then current->prev will be NULL, so current->prev->next will cause problems. You should check if current is the first item in the list before this line.
Also, your code leaks memory because you are allocating a new Node for current and you do not delete it. Since you are using current to move through the list rather than to create a new node, you should declare it as just
Node* current;
rather than
Node* current = new Node;