C++ - Single Linked List - Ideas - c++

I want to write a method to remove consecutive items with duplicate data values from a singly linked list. The method should return the number of items removed. The method should clean up memory as required, and should assume that memory was allocated using new.
For example, passing in the list
->a->b->c->c->a->b->b->b->a->null
should result in
->a->b->c->a->b->a->null
and return 3
The list item definition and function declaration are given below
struct litem {
char data;
litem* next;
};
int remove_consecutive_duplicates( litem*& list );
I have a simple logic to check the next element recursively & removing the element if its duplicate.
But, i would like to know how many efficient ways to do this ? All ideas welcome from C++ gurus..

You can use std::list, and before pushing element on it you must check:
if ((*l.rbegin()) == next)
{
return;
}
l.push_back(next);

in meta language:
item = items.first
while (item != null) {
while (item.next != null && item.value = item.next.value) {
temp = item.next
item.next = item.next.next
temp.dispose
}
item = item.next
}

As far as I can see, there's not a lot to optimize here. Returning the number of items used is just a case of incrementing a counter. Basically, if you find that litem->data == litem->next->data, then you need to do the removal like so:
litem* tmpItem = currentItem->next;
currentItem->next = tmpItem->next;
delete tmpItem;
Keep iterating until currentItem->next == NULL, to avoid referencing beyond the end of the list.

Related

Create a checkerboard or "Interweave" two linked-lists. IE changing the pointers of two linked lists

So I have two linked lists, each holding a color:
1.black->2.black->3.black->4.black->5.black->NULL
1.red ->2.red ->3.red ->4.red ->5.red ->NULL
I want the function to return
1.black->2.red ->3.black->4.red ->5.black->NULL
1.red ->2.black->3.red ->4.black->5.red ->NULL.
Lets name the first pointers, firstBlack and firstRed. To achieve this "checkerboard" pattern, I switch the nodes that each first is pointing to with a simple swap to the other list, advance the pointer two spots, then repeat until I'm at the end of the list.
while(firstBlack->next != NULL && firstRed->next != NULL) {
Node * temp = firstBlack->next;
firstBlack->next = firstRed->next;
firstRed->next = temp;
firstBlack = firstBlack->next->next;
firstRed = firstRed->next->next;
}
However, the function isn't doing what it's supposed to although I'm fairly certain that my logic is correct. I am also getting seg faults :(
This is a simple enough code, please use a debugger and debug the code step by step.
Also please post the entire code not just what's in the while loop.
This code should work correctly.
//Some methods to create these linked lists.
pBlackHead = CreateBlackList();
pRedHead = CreateRedList();
firstBlack = pBlackHead;
firstRed = pRedHead;
while(firstBlack->next != NULL && firstRed->next != NULL){
Node * temp = firstBlack->next;
firstBlack->next = firstRed->next;
firstRed->next = temp;
firstBlack = firstBlack->next;
firstRed = firstRed->next;}
While printing the list to check the correctness use pBlackHead , pRedHead. A debugger is not currently available on the system I am using but this should work.
You are advancing two steps without checking end conditions. Because you have an odd number of items, you dereference a null pointer.
You don't need to care which tail originated in which list to swap them
for(; left->next && right->next; left = left->next, right = right->next) {
std::swap(left->next, right->next);
}

Sort struct that contains pointer to the next

so I have something like:
struct Something
{
int number;
Something* next;
};
And I want to sort them, by the number, though I don't want to change the number, but I want to change the pointer to the next.
How would I do that?
I know the end and the beginning of the "list", (FIFO order)
Use MergeSort for linked lists: first traverse the list with two running pointers, one of them advancing twice slower. When you reach the end of the list, the slow pointer points to the middle. Split the list and sort the halves recursively, then Merge.
There are various sorting algorithms (http://www.sorting-algorithms.com/), and by far, I would use the random|selection one for this example. It will look something like:
void Something::SortAscending() {
Something* current = next;
Something* smallest = next;
while( current ) {
if( current->number < smallest->number ) {
smallest = current;
}
current = current->next;
}
if( smallest != next )
smallest->next = next;
next = smallest;
next->SortAscending();
}
Note, however, that if you're given the head of the list, you may not change it with the type of function I provided above.
Sort -> for each element of sorted array update next pointer

Deleting elements from doubly bounded pointer list

I am working on a project where I create a double bounded pointer list, delete several elements, and still be able to read off the list. I have a double bounded pointer list, but am having trouble deleting elements and keeping the list double bounded. This then causes issues when trying to print the list.
Below is the IF statement I've placed in a while loop to help delete unwanted elements. I keep getting a segmentation fault (core dumped).
if ((black2 != black)||(white2 != white)) {
dump = help;
help = help ->next;
dump -> before = temp;
temp -> next = help;
help ->before = temp;
delete dump;
}//if
else { temp = help;
help = help->next;
help ->before = temp; }//else
To maintain properly the doubly linked list you should do something like :
void remove(X *elt) {
X* before = elt->before;
X* after = elt->next;
if (before != NULL) { // assuming first element points to NULL
before->next = after;
}
else {
first = after; // assuming first is a pointer to first element of list
}
if (after != NULL) { // assuming last element points to NULL
after->before = before;
}
else {
last = before; // assuming last is a pointer to last element
}
delete elt;
}
That way, you ensure that elements around current correctly point to each other dealing with special cases of removing first or last element.
But you already have a std::list template in Standard Template Library
One logical issue in your code is the line dump->before = temp.
What this does is that it sets the previous node pointer of dump to temp, as opposed to defining temp as the previous node.
The correct line should read temp = dump->before
PS: Your code is correct assuming that the node you are deleting isn't the first or last node (and you haven't padded with dummy nodes). You should introduce checks for these cases if required.

Store link list node address

Im currently writing a descending sort function for a doubly link list. I have a flag for the largest value but wondering if there is a way to store the address of a node pointer so i can set its flag outside the loop when operations are done.
Thanks
In this case, our data is relevance
float findLargest(DoublyLinkList largestdata)
{
ListPlayHolder *findbiggest = largestdata.lhead;
float largest = findbiggest ->relevance;
while (findbiggest ->next != NULL)
{
if (findbiggest ->relevance > largest && findbiggest ->largestFlag != true)
{
largest = findbiggest ->relevance;
}
findbiggest = findbiggest->next;
}
return largest;
}
This is no fancy sort, just trying to make a simplistic descending sort of my data. Once i find the largest, i want to set its nodes flag to true. Just need a way to store the address.
If you used std::list you could use std::sort with different comparison functions and not have to change the node structure for every different ordering sequence.
Another idea is to place your items into a std::vector and create std::list<item *> for each item. This would allow you to access the items in the vector in various orders. For example, one list could be for ascending by title. Another could be descending by relevance.
As I understand it, you only need to keep a pointer to the largest element, so nothing fancy, just another ListPlayHolder*(which seems like the data type of a pointer to a node - a quite confusing name if you ask me, but whatever).
Also, I would recommend not to initalize largest with something pointed to by findbiggest - haven't seen your other list code, but I guess that pointer might be NULL if the list is empty.
You actually don't need to store the relevance value separately if you instead hold on to a pointer of the currently largest object (thanks #WhozCraig). Here's the modified code:
ListPlayHolder* findbiggest = largestdata.lhead;
ListPlayHolder* largest = findbiggest;
while (findbiggest && findbiggest ->next != NULL)
{
if (findbiggest ->relevance > largest->relevance && findbiggest->largestFlag != true)
{
largest = findbiggest;
}
findbiggest = findbiggest->next;
}
// here do whatever modifications you need to do to flags? or maybe return largestPtr?
largest->largestFlag = true;
return largest->relevance;

How to check whether a linked list is circular or not? [duplicate]

This question already has answers here:
How to detect a loop in a linked list?
(29 answers)
Closed 5 years ago.
How can I find whether a singly linked list is circular/cyclic or not? I tried to search but couldn't find a satisfactory solution. If possible, can you provide a pseudo-code or Java-implementation?
For instance:
1 → 3 → 5 → 71 → 45 → 7 → 5, where the second 5 is actually the third element of the list.
The standard answer is to take two iterators at the beginning, increment the first one once, and the second one twice. Check to see if they point to the same object. Then repeat until the one that is incrementing twice either hits the first one or reaches the end.
This algorithm finds any circular link in the list, not just that it's a complete circle.
Pseudo-code (not Java, untested -- off the top of my head)
bool hasCircle(List l)
{
Iterator i = l.begin(), j = l.begin();
while (true) {
// increment the iterators, if either is at the end, you're done, no circle
if (i.hasNext()) i = i.next(); else return false;
// second iterator is travelling twice as fast as first
if (j.hasNext()) j = j.next(); else return false;
if (j.hasNext()) j = j.next(); else return false;
// this should be whatever test shows that the two
// iterators are pointing at the same place
if (i.getObject() == j.getObject()) {
return true;
}
}
}
A simple algorithm called Floyd's algorithm is to have two pointers, a and b, which both start at the first element in the linked list. Then at each step you increment a once and b twice. Repeat until you either reach the end of the list (no loop), or a == b (the linked list contains a loop).
Another algorithm is Brent's algorithm.
Three main strategies that I know of:
Starting traversing the list and keep track of all the nodes you've visited (store their addresses in a map for instance). Each new node you visit, check if you've already visited it. If you've already visited the node, then there's obviously a loop. If there's not a loop, you'll reach the end eventually. This isn't great because it's O(N) space complexity for storing the extra information.
The Tortoise/Hare solution. Start two pointers at the front of the list. The first pointer, the "Tortoise" moves forward one node each iteration. The other pointer, the "Hare" moves forward two nodes each iteration. If there's no loop, the hare and tortoise will both reach the end of the list. If there is a loop, the Hare will pass the Tortoise at some point and when that happens, you know there's a loop. This is O(1) space complexity and a pretty simple algorithm.
Use the algorithm to reverse a linked list. If the list has a loop, you'll end up back at the beginning of the list while trying to reverse it. If it doesn't have a loop, you'll finish reversing it and hit the end. This is O(1) space complexity, but a slightly uglier algorithm.
I you count your Nodes and get to the *head again.
How about following approach:
Sort the link list in ascending order by following any standard algorithms.
Before sort: 4-2-6-1-5
After Sort: 1-2-4-5-6
Once sorted, check for each node data and compare with link node's data, something like this:
if(currentcode->data > currentnode->link->data)
i.e. circular = true;
At any comparison, if any of "currentnode->data" is greater than "currentcode->link->data" for a sorted link list, it means current node is pointed to some previous node(i.e circular);
Guys, i dont have setup to test the code.Let me now if this concept works.
Use the Tortoise-Hare algorithm.
A algorithm is:
Store the pointer to the first node
Traverse through the list comparing each node pointer to this pointer
If you encounter a NULL pointer, then its not circularly linked list
If you encounter the first node while traversing then its a circularly linked list
#samoz has in my point of view the answer! Pseudo code missing. Would be something like
yourlist is your linked list
allnodes = hashmap
while yourlist.hasNext()
node = yourlist.next()
if(allnodes.contains(node))
syso "loop found"
break;
hashmap.add(node)
sorry, code is very pseudo (do more scripting then java lately)
Start at one node and record it, then iterate through the entire list until you reach a null pointer or the node you started with.
Something like:
Node start = list->head;
Node temp = start->next;
bool circular = false;
while(temp != null && temp != start)
{
if(temp == start)
{
circular = true;
break;
}
temp = temp->next;
}
return circular
This is O(n), which is pretty much the best that you will able to get with a singly linked list (correct me if I'm wrong).
Or to find any cycles in the list (such as the middle), you could do:
Node[] array; // Use a vector or ArrayList to support dynamic insertions
Node temp = list->head;
bool circular = false;
while(temp != null)
{
if(array.contains(temp) == true)
{
circular = true;
break;
}
array.insert(temp);
temp = temp->next;
}
return circular
This will be a little bit slower due to the insertion times of dynamic arrays.
Here is a nice site on which the different solutions can copied.
find loop singly linked list
This is the winner on that site
// Best solution
function boolean hasLoop(Node startNode){
Node slowNode = Node fastNode1 = Node fastNode2 = startNode;
while (slowNode && fastNode1 = fastNode2.next() && fastNode2 = fastNode1.next()){
if (slowNode == fastNode1 || slowNode == fastNode2) return true;
slowNode = slowNode.next();
}
return false;
}
This solution is "Floyd's
Cycle-Finding Algorithm" as published
in "Non-deterministic Algorithms" by
Robert W. Floyd in 1967. It is also
called "The Tortoise and the Hare
Algorithm".
It will never terminate from the loop, it can also be done in following solution:
bool hasCircle(List l)
{
Iterator i = l.begin(), j = l.begin();
while (true) {
// increment the iterators, if either is at the end, you're done, no circle
if (i.hasNext()) i = i.next(); else return false;
// second iterator is travelling twice as fast as first
if (j.hasNext()) j = j.next(); else return false;
if (j.hasNext()) j = j.next(); else return false;
// this should be whatever test shows that the two
// iterators are pointing at the same place
if (i.getObject() == j.getObject()) {
return true;
}
if(i.next()==j)
break;
}
}
Try this
/* Link list Node */
struct Node
{
int data;
struct Node* next;
};
/* This function returns true if given linked
list is circular, else false. */
bool isCircular(struct Node *head)
{
// An empty linked list is circular
if (head == NULL)
return true;
// Next of head
struct Node *node = head->next;
// This loop would stope in both cases (1) If
// Circular (2) Not circular
while (node != NULL && node != head)
node = node->next;
// If loop stopped because of circular
// condition
return (node == head);
}