Adding to a Sorted Doubly LinkedList (C++) - c++

I've implemented a program that creates a sorted doubly linked list. Everything works fine except the fact that I can't seem to figure out where program is accepting the node 66 as head, and 44 (which is smaller) as the node after. Here's my add function.
bool SortedDoublyLinkedList<ItemType>::add(const ItemType &newEntry) {
Node<ItemType> *newNode = new Node<ItemType>();
newNode->setItem(newEntry);
if (size == 0) //checks if linked list is empty -> add elements if so.
{
head = newNode;
newNode->setNext(NULL);
newNode->setPrev(NULL);
tail = newNode;
}
// checks if the new node to be added is small than node that head is currently pointing to. If so, add new node before head and make it the new head of list.
else if (newNode->getItem() < head->getItem()) {
head->setPrev(newNode);
newNode->setNext(head);
newNode->setPrev(NULL);
head = newNode;
}
// checks if new node is bigger than the tail node (or last node). If so, add new node to end of list. Then make that new node the tail (end) of list.
else if (newNode->getItem() > tail->getItem()) {
tail->setNext(newNode);
newNode->setNext(NULL);
newNode->setPrev(tail);
tail = newNode;
}
// if the new node is neither of the mentioned situations, add the new node in the correct position in middle of the list. TempPtr1 acts as a ptr and the new node will be added directly in front of it.
else {
Node<ItemType> *tempPtr1;
tempPtr1 = head;
while (newNode->getItem() > tempPtr1->getItem()) {
tempPtr1 = tempPtr1->getNext();
}
newNode->setPrev(tempPtr1->getPrev());
newNode->setNext(tempPtr1); // = tempPtr1;
tempPtr1->getPrev()->setNext(newNode);
tempPtr1->setPrev(newNode);
}
size++;
return true;
}
Output:
66
44
88
88

Related

Adding a node to the beginning of a double-linked list

I am trying to create a function that adds a node to the beginning of a double-linked list in C++, and I'm getting this error in Xcode. I know it must be because I lost the address of one of my temp nodes, but I cannot figure out how to fix it.
template<typename Item>
void DLList<Item>::push_front(const Item &item) {
/* Adds item to a new Node at the front of the list. Updates head,
tail, and size accordingly. Must appropriately handle cases in which the list is empty */
Node*p = new Node;
p -> item = item;
Node*oldHead = head;
p -> next = oldHead;
oldHead -> prev = p; /*error message: Thread 1: EXC_BAD_ACCESS (code=1, address=0x10)*/
head = p;
size ++;
}
The error will happen when oldHead is nullptr, and then oldHead->prev is an invalid access. This happens when the list is empty (head is nullptr).
It is easy to fix: just make sure you only execute that statement when the list is not empty. NB: you don't actually need oldHead. Just keep working with head.
And as the comment in your code seems to suggest your list has a tail member, you should set it when the first node is added to the list:
Node* p = new Node;
p -> item = item;
p -> next = head;
if (head != nullptr) {
head -> prev = p;
} else {
tail = p;
}
head = p;
size ++;

Selection sort in single linked list without using swap

I have been trying to solve the selection sort in single linked list without using swap nodes. Using a temp list to store nodes and assign the current list with a new one
//my addlastnode function
void AddLastNODE(LIST &mylist, NODE *p)
{
//Check the list is empty or not
if(isEmpty(mylist))
mylist.pHead = mylist.pTail = p;
else
mylist.pTail->pNext = p;
mylist.pTail = p;
}
void selectionSort(LIST &mylist)
{
//Initialize a temp list to store nodes
LIST mylisttemp;
IntList(mylisttemp);
//Create node
NODE *p;
NODE *i;
//Create min node
NODE *min;
//Check if list is empty or has one node
if(mylist.pHead == mylist.pTail)
return;
//Traverse the list till the last node
for(p=mylist.pHead; p->pNext!=NULL && p!=NULL; p = p->pNext)
{
min=p;
for(i=p->pNext; i!=NULL;i=i->pNext)
{
////Find the smallest data in list
if(i->data < min->data)
min=i;
}
////Add the smallest to a new list
AddLastNODE(mylisttemp, min);
}
//Fill the current list to the new list
if(!isEmpty(mylisttemp))
mylist = mylisttemp;
}
Your code does not reduce the list you are selecting nodes from: the selected node should be removed from it. To make that happen, you need a reference to the node before the selected node, so that you can rewire the list to exclude that selected node.
There is also a small issue in your AddLastNODE function: it does not force the tail node to have a null as pNext pointer. This may be a cause of errors when the function is called with a node that still has a non-null pNext pointer. Secondly, the indentation is off around the else block. It does not lead to a bug in this case, but still it is better to avoid the confusion:
void AddLastNODE(LIST &mylist, NODE *p)
{
if(isEmpty(mylist))
mylist.pHead = p;
else
mylist.pTail->pNext = p;
mylist.pTail = p; // indentation!
p->pNext = nullptr; // <--- better safe than sorry!
}
Then to the main algorithm. It is quite tedious to work with a previous node reference when looking for the node with the minimum value. It helps a bit when you temporarily make the input list cyclic:
void selectionSort(LIST &mylist) {
if (mylist.pHead == mylist.pTail) return;
// Make list temporarily cyclic
mylist.pTail->pNext = mylist.pHead;
LIST mytemplist;
IntList(mytemplist);
while (mylist.pHead != mylist.pTail) {
// Select node:
NODE * beforemin = mylist.pTail;
for (NODE * prev = mylist.pHead; prev != mylist.pTail; prev = prev->pNext) {
if (prev->pNext->data < beforemin->pNext->data) {
beforemin = prev;
}
}
NODE * min = beforemin->pNext;
// Extract selected node:
if (min == mylist.pTail) mylist.pTail = beforemin;
if (min == mylist.pHead) mylist.pHead = min->pNext;
beforemin->pNext = min->pNext;
// And insert it:
AddLastNODE(mytemplist, min);
}
// Move last remaining node
AddLastNODE(mytemplist, mylist.pHead);
// Copy back
mylist = mytemplist;
}
As a side note: You might even want to always keep your list cyclic. This will mean some changes in other functions you may have, as there will be no pNext pointers that are null then.

Merge two sorted Linked List

I had a doubt in this problem: link I am following this solution:
if((headA==NULL)&&(headB==NULL)
return NULL;
if((headA!=NULL)&&(headB==NULL))
return headA;
if((headA == NULL)&&(headB!=NULL))
return headB;
if(headA->data < headB->data)
headA->next = MergeLists(headA->next, headB);
else if(headA->data > headB->data)
{
Node* temp = headB;
headB = headB->next;
temp->next = headA;
headA = temp;
headA->next = MergeLists(headA->next, headB);
}
return headA;
I get that when headA->data < headB->data then we simply move the headA pointer to the next node. But when headA->data > headB->data, then we create a temp pointer, point it where headA is pointing and move headB to next node. What I don't get is:
How are the nodes which are previously sorted get linked to this new temp node that I have created? Can you please point it out on my code
Also, where is headA pointer pointing to after the second condition? Is it pointing at the new node?
The code effectively moves the head element from list B to list A.
Node* temp = headB;
headB = headB->next;
temp is pointing at the list B head, and headB is pointing at the list B tail. In effect, the list B head has been popped off the list.
temp->next = headA;
The list A is now appended to the popped head.
headA = temp;
And list A is now set to the list with the original head from list B followed by the original list A.
The merge then proceeds exactly as if list A had the smaller head, which it now does because the next element in list B cannot be smaller than it.
This code fails to handle the case that both lists have the same head data value. In that case, it just returns list A without merging the tails.
Not sure why you can't just do this for the last two cases:
if(headA->data < headB->data) {
headA->next = MergeLists(headA->next, headB);
return headA;
}
else {
headB->next = MergeLists(headA, headB->next);
return headB;
}
And keep it simple and symmetric.
You can also simplify the first three cases to the following two:
if(headA == NULL)
return headB;
if(headB == NULL)
return headA;
This can also be done without recursion:
Node *merge_lists(Node *headA, Node *headB)
{
Node *head;
Node **nextPtr = &head;
while (headA && headB) {
Node **headMin = (headA->data < headB->data) ? &headA : &headB;
*nextPtr = *headMin;
nextPtr = &(*headMin)->next;
*headMin = *nextPtr;
}
*nextPtr = headA ? headA : headB;
return head;
}

Conversion errors? (i.e '!=' no conversion FDHPolynomial from 'nullptr' to 'int')

I was making this add function definition but I keep getting these conversion errors and I think I called a class or function wrong but I do not really understand or can find what's causing the errors. (Sorry about the long function, I tried to cut it down)
template<class ItemType>
bool FDHPolynomial<ItemType>::add(const ItemType& newCoefficient, const ItemType& newExponent)
{
if (newCoefficient == 0)//not wasting memory to store 0
{
return false;//no node added
}
else if (isEmpty())//if this is the first node added
{
FDHNode<ItemType>* newNodePtr = new FDHNode<ItemType>();//create new node
newNodePtr->setCoeffi(newCoefficient);//set contents
newNodePtr->setExpon(newExponent);
newNodePtr->setNext(nullptr);//since this is the only node, next value is nullptr
headPtr = newNodePtr;//first node is the head node
itemCount++;
}
else if (contains(newExponent))//if a node of this degree exists, add to its exponent
{
FDHNode<ItemType>* nodeToModifyPtr = getPointedTo(newExponent);//find the existing node
ItemType sumCoefficient = newCoefficient + nodeToModifyPtr->getCoeffi();//add new coefficient to existing coefficient
if (sumCoefficient == 0)//if added value cancels out a value
{
remove(newExponent);
}
else
{
nodeToModifyPtr->setCoeffi(sumCoefficient);//apply sum of coefficients
}
//itemCount does not increment
}
else if (newExponent > degree())//if new exponent is greater than any existing exponents
{
FDHNode<ItemType>* newNodePtr = new FDHNode<ItemType>();//create new node
newNodePtr->setCoeffi(newCoefficient);//set contents
newNodePtr->setExpon(newExponent);
newNodePtr->setNext(headPtr);//place at front of the chain
headPtr = newNodePtr;//new node is now the head node
itemCount++;
}
else//if new node needs to be inserted somewhere after the head node
{
FDHNode<ItemType>* newNodePtr = new FDHNode<ItemType>();//create new node
newNodePtr->setCoeffi(newCoefficient);//set contents
newNodePtr->setExpon(newExponent);
FDHNode<ItemType>* curPtr = headPtr;//this pointer will cycle through nodes until either a node with a degree smaller than newExponent is found or the last node is reached
while ((curPtr->getExpon() > newExponent) && (curPtr->getNext() != nullptr))
{
curPtr = curPtr->getNext();//advance curPtr
}

Linked list copy constructor

I originally had to create my own linked list with using the STL. Now, I am to implement a copy constructor method and I am having real difficulty understanding it. Have a test on this in a few days so I would really like to get it clear. (Test is closed book so need to really).
The List contains a EmployeeNode pointer *head. The EmployeeNode contains an Employee and a pointer to the next EmployeeNode. The Employee class contains a name and salary.
The method seems to get caught in the for loop when trying to copy the 3rd node over. I think this is because I overwrite the newNode but I do not know how to solve this.
ListOfEmployee::ListOfEmployee(const ListOfEmployee &obj)
{
head = NULL;
if(obj.head != NULL)
{
EmployeeNode *newNode = new EmployeeNode("", 0);
EmployeeNode *tempPtr;
EmployeeNode *newPtr;
//using the temp pointer to scroll through the list until it reaches the end
for(tempPtr = obj.head; tempPtr->next !=NULL; tempPtr = tempPtr->next)
{
if(head == NULL)
{
cout<<"Attempts to initialize the head"<<endl;
head = newNode; //assinging the new node to the head
newNode->emp.name = tempPtr->emp.name;
newNode->emp.salary = tempPtr->emp.salary;
cout<<"Initializes the head"<<endl;
}
else
{
cout<<"Attempts to add a new node"<<endl;
//using the temp pointer to scroll through the list until it reaches the end
for(newPtr = head; newPtr->next !=NULL; newPtr = newPtr->next)
{
cout<<"Looping through the list"<<endl;
}
//assiging the last place to the new node
newPtr->next = newNode;
newNode->emp.name = tempPtr->emp.name;
newNode->emp.salary = tempPtr->emp.salary;
cout<<"Adds a new node"<<endl;
}
}
}
}
In your code where you are adding newNode in newPtr->next = newNode; you are basically using previously allocated node. You should create a new node using new. Something like:
newPtr->next = new EmployeeNode("", 0);
newNode = newPtr->next;
newNode->emp.name = tempPtr->emp.name;
newNode->emp.salary = tempPtr->emp.salary;
Also you should set newNode->next = NULL; in your code.