Doubly Linked List Bubble Sort - c++

My project is a bubble sort system for doubly linked list.
I am trying to sort elements of doubly linked list (which are objects) by Date.
I used pointer-based sort because I do not want to change the data of pointers.
The problem is my code can (I think efficiently) sort the linked list. But in the end, when I try to print objects of linked list, my head is not in place where it should be. Could you help me?
struct DoubleNode *DoubleDynamic::swap( DoubleNode *pointer1, DoubleNode *pointer2) {
DoubleNode* temp=pointer2->next;
pointer2->next=pointer1;
pointer2->prev=pointer1->prev;
pointer1->next=temp;
pointer1->prev=pointer2;
return pointer2;
}
void DoubleDynamic::sort(int size)
{
DoubleNode* temp;
DoubleNode* current;
bool sorting;
if (head==NULL)
{
return;
}else
{
for (int i = 0; i <= size; ++i)
{
sorting= false;
temp=head;
for (int j = 0; j < size-1-i; ++j)
{
DoubleNode *employee1=temp;
DoubleNode *employee2=employee1->next;
if (employee2!=NULL)
{
if (employee1->data->getAppointment().operator>(employee2->data->getAppointment()))
{
temp = swap(employee1,employee2);
sorting= true;
}
temp= temp->next;
}
}
if (!sorting)
{
break;
}
}
}
current=head;
while (current->prev!=NULL)
{
current=current->prev;
}
head=current;
}
void DoubleDynamic::display()
{
struct DoubleNode *trav;
trav=head;
if (trav==NULL)
{
cout<<"Liste boş yaa"<<endl;
}
while (trav != NULL)
{
cout<<*(trav->data)<<endl;
trav=trav->next;
}
cout<<endl;
}

The problem is that when you swap the head pointer, you don't update head to refer to the new head node.
One way to address this is after you do the swap, you should check to see if the head pointer should be updated.
temp = swap(employee1,employee2);
if (employee1 == head)
head = temp;
Alternatively, in swap, if the new prev pointer assigned in pointer2->prev=pointer1->prev; is NULL then update the head (because the head node does not have a previous node).
if ((pointer2->prev=pointer1->prev) == nullptr)
head = pointer2;

Related

How can i change two different nodes from two different doubly linked list?

i have 2 doubly linked list within nodes, i compare data of nodes and if data of node of second list is bigger than data of node of first list, i will chande nodes. How can i do that.
this deletes old nodes and adds that given nodes.
void DoubleLinkedList::SwitchNodesFromList(Node* changeNode, int index)
{
RemoveAt(index);
if (index < 0 || index > size)
throw "Error";
if (index == 0)
{
head = changeNode;
if (head->next != NULL)
head->next->prev = head;
}
else
{
Node* prv = findPreviousByPosition(index);
prv->next = changeNode;
if (prv->next->next != NULL)
prv->next->next->prev = prv->next;
}
}
that keeps nodes these will change
void ListController::SwitchNodes(Node* firstNodeOfList, Node* secondNodeOfList, int index)
{
Node* first = firstNodeOfList;
Node* second = secondNodeOfList;
Node* temp = first;
first->next = second->next;
first->prev = second->prev;
second->next = temp->next;
second->prev = temp->prev;
firstList->SwitchNodesFromList(second, index);
secondList->SwitchNodesFromList(first, index);
delete temp;
}
i compare item but i cant switch nodes
void ListController::CompareItemsOfNodes()
{
for (int i = 0; i < firstList->Count(); i++)
{
if (firstList->ElementAt(i) > secondList->ElementAt(i))
{
ReverseList(firstList);
}
else if (firstList->ElementAt(i) == secondList->ElementAt(i))
{
ReverseList(secondList);
}
else if (firstList->ElementAt(i) < secondList->ElementAt(i))
{
SwitchNodes(firstList->GetNode(i), secondList->GetNode(i), i);
}
}
}

Printing Linked List prints only the head node

After randomly filling a linked list with a deck of 52 cards. When I try to print it, it will print the head node 52 times. Is there something wrong with my 'traverse through linked list logic' or something wrong with my insertion logic?
These are the Node helper methods (a bagNode has a CardOfBag and a next)
card *bagNode::getCard() // retreives card in the bagnode as pointer
{
return this->cardOfBag;
}
bagNode *bagNode::getNext() // retreives the next bagnode as pointer
{
return this->next;
}
void bagNode::setCard(card *card) // sets card of bagnode
{
this->cardOfBag = card;
}
void bagNode::setNext(bagNode *setNode) // sets next bagnode
{
setNode->next = this->next;
this->next = setNode;
}
These are the methods for the linked list (called bag):
it has a header, tail, and current bagNode* pointers.
void bag::add(bagNode *node) // adds node to random position
{
int i, place, size;
place = randomPosition();
size = getCurrentSize();
if (size == 0) // for initial insertion into empty linked list
{
setHead(node);
setTail(node);
alterSize(1);
} else {
if ((size - 1) == place) // if the insertion is at the last node
{
this->tail->setNext(node);
setTail(node);
alterSize(1);
} else {
if (place == 0) // if insertion is at head node
{
node->setNext(this->head);
setHead(node);
alterSize(1);
} else {
setCurrent(place); // for any insertion in between first and last nodes
node->setNext(current->getNext());
current->setNext(node);
alterSize(1);
}
}
}
}
int bag::getCurrentSize() // returns size of bag (linked list)
{
return this->size;
}
void bag::alterSize(int num) // changes the size int of bag by num
{
this->size = this->size + num;
}
int bag::randomPosition() // generates random number from 0 to size exclusive
{
int size = getCurrentSize();
if (size != 0)
return (rand() % size);
}
void bag::setCurrent(int desiredPosition) // this traverses the current pointer
// by desiredPosition steps from the head node
{
int i;
this->current = this->head;
for (i = 0; i < desiredPosition; i++) {
this->current->setNext(this->current->getNext());
}
}
bagNode *bag::getCurrentNode() // returns node of current pointer
{
return this->current;
}
bagNode::setNext() is supposed to make next point to the node provided; leave the other node alone:
void bagNode::setNext(bagNode* setNode) //sets next bagnode
{
this->next = setNode;
}
Your bag::setCurrent() doesn't work. You're supposed to make this->current keep going "next" until you hit the desiredPosition, instead you're only changing its next pointer to... the same value it previously had.
Do something like this instead:
void bag::setCurrent(int desiredPosition)
{
int i;
this->current = this->head;
for(i = 0; i < desiredPosition; i++)
{
this->current = this->current->getNext();
}
}
That should work better now.
in your function
void bag::setCurrent(int desiredPosition)
You are not changing this->current at all. Basically you did nothing in that function.

Create a function to insert element into List at given position

Not sure if there is a simple and better way to implement this function?
void insert(Node* &head, int element, int position) {
Node* current = new Node;
current->data = element;
current->next = NULL;
if (position == 1) {
current->next = head;
head = current;
return;
}
else {
Node * current2 = head;
for (int i = 0; i < position - 2; i++) {
current2 = current2->next;
}
current2->next = current2->next;
current2->next = current;
}
}
A better way would be to make this function without null pointer access. You are missing all the necessary error checking.
But if you have to use this function you are already doing something wrong. The operation takes O(n) time. And if you build your list using only this function then you already have O(n^2) time. Using a balanced tree or heap would give you O(n * log n) time which makes a huge difference even for relatively small n. So think again why you need to insert at a given position and think about more suitable data structures.
A simpler implementation, and actually used in real code a lot, is to implement insert_before(before, data) or insert_after(after, data) with a doubly linked list. Both of which would get an item in the list and a new item to insert and place the new item before or after the old one on O(1) time.
Some boundary check is needed (please find the comments inline):
int listLen(Node *head)
{
int len = 0;
while (head != nullptr)
{
len++;
head = head->next;
}
return len;
}
void insert(Node* &head, int element, int position)
{
if (head == nullptr) // do nothing if head is nullptr
return;
if (position < 0) // insert to the begin if position is negative
position = 0;
else
{
int len = listLen(head);
if (len < position) // position is out of range, insert to the end
{
position = len;
}
}
if (position == 0)
{
Node *next = head;
head = new Node(element);
head->next = next;
}
else
{
int curPos = 0;
Node *curNode = head;
while (curPos < position - 1) // move to position
{
curNode = curNode->next;
curPos++;
}
Node *next = curNode->next; // do insertion
curNode->next = new Node(element);
curNode->next->next = next;
}
}

Implementing a hasNext function in a C++ linked list

I'm attempting to write a function to see whether or not there are more nodes to search through in the linked list, and what I have so far gives me a seg fault. Any ideas on what I need to change?
Iterator class:
bool Iterator::hasNext(){
Node* temp = current->getNext();
if(temp == NULL){
return(false);
}
else{
return(true);
}
List Class:
void List::addFirst(void* obj)
{
Node* newNode = new Node(obj);
newNode->setNext(head);
head = newNode;
}
Node Class:
Node* Node::getNext()
{
return(next);
}
Main class:
List list1;
for(int i = 0; i < 4; i++) {
list1.addFirst(stars[i]);
}
Iterator itr(&list1);
while(itr.hasNext()) {
std::cout << ((char*)itr.get()->getItem())
<< std::endl;
itr.advance();
}
I am not sure about it but you can
Try
//directly accessing the next and comparing
return if(current->getNext() == NULL)
directly without storing it in a separate temp node .

C++ (Arduino) linked list, memory not freed when deleting a node inside the list

I am developing a Client for an Arduino like plattform and I am trying to use a generic LinkedList library to organise objects. The list consists of the following defined nodes:
template<class T>
struct ListNode
{
T data;
ListNode<T> *next;
};
However, I ran into memory problems while using the linked list. I found out that the memory is not freed when deleting nodes inside the list but I cannot figure out why since the element is obviously removed from the list. In addition, the memory is always freed when deleting the last node of the list. I am using the following destroy method for deleting elements in the list:
template<typename T>
void LinkedList<T>::destroy(int index){
if(index < 0 || index >= _size)
return;
if(index == 0) {
if (_size == 1) {
delete root->data;
delete root;
root=NULL;
last=NULL;
_size=0;
lastNodeGot = root;
lastIndexGot = 0;
isCached = false;
return;
} else {
ListNode<T> *tmp = root->next;
delete root->data;
delete root;
root = tmp;
_size--;
lastNodeGot = root;
lastIndexGot = 0;
isCached = false;
return;
}
}
ListNode<T> *tmp = getNode(index - 1);
ListNode<T> *toDelete = getNode(index);
tmp->next = toDelete->next;
delete toDelete->data;
delete toDelete;
if (tmp->next == NULL) {
last=tmp;
}
_size--;
lastNodeGot = tmp;
lastIndexGot = index-1;
isCached = false;
return;
}
If I delete all elements with the method above so that the list is empty, the memory is fully freed. However, the list is used in the client quite frequently with add/delete operations but it gets never emptied completely.
Btw. I am storing pointers to objects in the list like Strings.
Is there anything wrong with the code? Thank you in advance.