Insertion in ordered linked list - c++

I'm trying to insert a node in a linked list so that the nodes are ordered in ascending mode by de idx parameter.
void add(int i){
if(find(i)==NULL){ //if node does not exist
node *m=new node;
m->idx=i;
m->values=NULL;
m->next=NULL;
if(list==NULL){ //if list is empty
list=m;
return;
}
if(i < list->idx){ //if the new node comes before the head node
m->next=list;
list=m;
return;
}
//if the new node is bigger than the maximum node index in the list
if(i > maxIdx(list)){
node *last=lastNode(list);
last->next=m;
}
//else normal insertion
node *prev=list;
node *curr=list->next;
while(curr!=NULL){
if( i < curr->idx){
m->next=curr;
prev->next=m;
return;
}
prev=curr;
curr=curr->next;
}
}
}
Edited with correct implementation, the fourth if was missing before.

It seems correct to me as well, as far as segfault is concerned. However, you don't consider the case when i is greater than the largest number in the list. In this case, you should insert i at the end of the list. So try fixing this bug first, maybe it will fix the segfault as well (which is coming from elsewhere, maybe from your find() implementation).
Now it seems that is the answer (as your comment on my comment confirms it).

Related

Removing duplicates from a sorted list (New Approach)

This is my program for removing duplicates from a sorted linked list. I am traversing from the head node of the linked list and using temp1 variable, I am checking whether there are any duplicates of the same value. If we find a data which is different from the current node, then we link that to current node and make it current node and repeat the process.
Here is the question:-
https://leetcode.com/problems/remove-duplicates-from-sorted-list/
ListNode* deleteDuplicates(ListNode* head) {
ListNode *curr=head,*temp1,*forw;
while(curr!=NULL)
{
//temp1 checks for next distinct element
temp1=curr->next;
while(temp1!=NULL)
{
//checking if the value at temp1 is distinct from current
if(temp1->val!=curr->val)
{
forw=temp1; //stored the distinct value in forw for reference to curr
break;
}
temp1=temp1->next;
}
curr->next=forw; // linked the distinct value to current
curr=curr->next;
}
return head;
}
But, the program is giving TLE(Time Limit Excedeed) Error.I have dry runned the code and it's working fine for me. I think i am missing some edge. Any help will be greatly appreciated?
You have UB for list of one element, as forw is then used uninitialized.
(that UB should probably do, in your case, infinite loop, so TLE).

Indexed singly linked list

I want to create a singly linked list with. I already have an implementation that does not permit indexing on it.
I would like to add this feature but I am not sure how to do that.
So basically the head should have index "1". But I can't figure it out myself what am I supposed to do in If statement to increase the index by 1 each step.
void AddNode (int addData)
{
nodePtr NewNode = new node;
NewNode->next = NULL;
NewNode->data = addData;
if (head != NULL)
{
curr = head;
while(curr->next != NULL)
{
curr = curr->next;
}
curr->next = NewNode;
NewNode->index;
}
else
{
head = NewNode;
NewNode->index = 1;
}
}
You mean for the ability to do something like get a linked list node via a get(index)?
Also, your head should not have index 1, it should be 0. This does not comply with standard practice of zero-based indexing.
A linked list does not technically have indexes nor should it store them. It seems like a linked list might not be the right data structure for what you are doing, however you can treat it like so with a loop like this (excuse if my c++ syntax is rusty)
int get(int index) {
Node current = head;
for (int x = 0; x < index; x++) {
if (current->next == null) {
//some sort of error handling for index out of bounds
} else {
current = current->next;
}
}
return current->data
}
get(2) would return the 3rd element of the list.
Graph for the structure
Why do you want to add it to the end of the list? Just simply add the new node to the front.
I don't think it is necessary to follow the order of 1,2,3.... Instead, you can do it reversely
Before you add a new node, you visit the head and find the index(i)of it. When you add the new one, the index of this one will be i+1.
Two advantages:
- It doses not change anything when you loop through this list.
- You know how many you have added into this list.
So what you really want to do is to add the ability to index elements of a linked list.
There is no need to actually store the index anywhere (as you don't really store the index of an array/vector element as the type and the address of the first element of the array is everything you need to retrieve the i-th element).
The only information you want to keep is the length of the list since computing it is costly because you have to traverse the list from head to tail every time you need it. Once you have this information the addNode should only update the size of the list.
As you already know accessing the i-th elements of a linked list is also costly (compared to a vector), but it is easy to code.
Something like the following should work:
void get(Node* head, size_t pos) {
while (head && pos--)
head = head->next;
return pos<=0 ? head : nullptr ;
}
It traverses the list from the head until it either reaches the end (head is nullptr) or pos is <=0.
Once you are out of the loop if pos>0 means that the list is shorter than pos otherwise you can return head (which will point to the pos-th element)

deleting a node anywhere in a linked list

I know how to remove a node from the front of a singly linked list, but I have no idea how to remove one from any arbitrary location.
In my specific problem, I continue to pass an integer value x into each node in the linked list. I can add and delete, but there is a function I need to write where if I've identified two x's that are the same, I delete the other instance.
I can give examples of my code if anyone needs examples of what I've done so far. Thanks for any and all responses
Also, I'm working with a singly linked list.
this is a disadvantage that singly linked list has. It requires iteration to perform deletion since you can not find the previous element of an arbitrary element. What you can find is its next element. You have to iterate from the head of the lists to find its previous element.
Hope this helps.
Because each node only has a link to the subsequent node, you would have to iterate over the entire list to obtain the previous element, then link the previous with the next node. (next, as in the one after that you wish to remove)
What I was doing, when I was looking into lists, and what not is: when iterating through list, I kept the pointer to the previous element in a separate variable, and if I decided that I needed to delete current element, I already had the pointer to the previous element at hand.
So, pseudo-code wise (to better illustrate it), it would be something like this:
prevValue = NULL
for curValue = root; curValue != NULL; curValue = curValue->Next
LOOP
IF *need to delete curValue*
THEN
IF prevValue == NULL
THEN
root = curValue->Next
delete curValue
curValue = root
ELSE
prevValue->Next = curValue->Next
delete curValue
curValue = prevValue
END IF
END IF
prevValue = curValue
END LOOP
noderemove(nodehead,int d){
if(head==NULL)
cout<<"empty linked list\n";
else {
node*curr=head,*pre=NULL;
while (curr!=NULL && curr->data !=d)
{
pre=curr;
curr=curr->next;
}
if(curr==NULL)
cout<<"Mahloch this number not found\n";
else {
if(pre==NULL)
head=curr->next;
else
pre->next=curr->next;
curr->next=NULL;
delete(curr); }
}return head;
}

deleting an item in cicular linked list

My program is supposed to do 3 operations:
Insert
Delete
Show on a circular linked list.
My problem is in the delete function. here is the code:
void c_list::del()
{
int num;
if(isempty())
cout<<"List is Empty!"<<endl;
else
{
node *temp1=first;
node *temp2=NULL;
cout<<"Enter the number that u want to DELETE:"<<endl;
cin>>num;
while(temp1->next!=first && temp1->info != num)
{
temp2=temp1;
temp1=temp1->next;
}
if(num != temp1->info )
cout<<"your number was not found in the list"<<endl;
else
{
if(temp2!=NULL)
{
temp2->next=temp1->next;
cout<<temp1->info<<" was deleted"<<endl;
}
else
{
first=temp1->next;
cout<<temp1->info<<"was deleted"<<endl;
}
}
}
system("pause");
}
Delete function is working in this way: user enters a number, the program searches that number & when it founds the number, removes it from the list.
Now the problem is that, when the user enters a number that does not exist in the list, the "App crash window" appears(I mean this window:Program is not responding), while I have a provided an error message for this case("your number was not found in the list")!!
Can u tell me what the problem is?
Your insert routine is not creating a circular list. When the list is empty and the initial item is inserted first == NULL. In this case your code leaves the list in a non-circular state. Because:
newitem->next=first;
if(first==NULL)
first=newitem;
At this point first->next == NULL, which should never be the case in a circular list. Your search code fails whenever the item to be found does not exist in the list. This is because it never cycles back around to the first node, since the list is not circular.
I think in your while loop you are reaching to the end of list and
after below line temp1 gets NULL.
temp1=temp1->next;
Then you are trying to read info attribute from null pointer and this causes error.
if(num != temp1->info )
I know you said it is circular list but i am not sure it is implemented correctly or not. My suggestion is just try to print temp1->info after while loop to be sure that correctness of list and your implementation.
Happen that, if you insert a number that is not in list, you have a loop in the first while.
So:
node* temp1 = first;
node* temp2 = 0;
while(temp1->next!=first && !temp2) {
if(temp1->info == num) {
/* save pointer and exit from while */
temp2 = temp1;
} else {
temp1 = temp1->next;
}
}
Then your code produce garbage because you never call a delete.
Most likely the problem is on the insert method, where maybe, you don't assign correcly pointers.
And then, why system("pause"); ? Take a look here.

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