iterating through queue with circular linked lists - c++

I have to implement a queue by using circular linked lists with only one iterator. My doubt is which is the better way in terms of performance, maintaining an iterator to the first item or from the last item?

Well, if you have a pointer to the first item, then operations on the end of the list are going to be O(N). With a pointer to the end of the list, you can do operations on both the beginning and the end in O(1). Generally, if you have a circularly linked list, then you want to be able to reach the beginning and the end, so the answer is that you performance will be better with a pointer to the end.

Related

why Run-time for add-before for doubly-linked lists is O(1)?

In data structures, we say pushing an element before a node in singly-linked lists are O(n) operation! since there is no backward pointers, we have to walk all the way through the elements to get to the key we are going to add before the new element. Therefore, it has a linear run time.
Then, when we introduce doubly-linked lists, we say the problem is resolved and now since we have pointers in both directions pushing before becomes a constant time operation O(1).
I understand the logic but still, something is confusing to me! Since we DO NOT have constant time access to the elements of the list, for finding the element we want to add before, we have to walk through the previous element to get there! that is true that in the doubly-linked list it is now faster to implement the add-before command, but still, the action of finding the interested key is O(n)! then why we say with the doubly-linked list the operation of add before becomes O(1)?
Thanks,
In C++, the std::list::insert() function takes an iterator to indicate where the insert should occur. That means the caller already has this iterator, and the insert operation is not doing a search and therefore runs in constant time.
The find() algorithm, however, is linear, and is the normal way to search for a list element. If you need to find+insert, the combination is O(n).
However, there is no requirement to do a search before an insert. For example, if you have a cached (valid) iterator, you can insert in front of (or delete) the element it corresponds with in constant time.

Single linked lists & time complexity

I'm trying to write my own (as close to standard as possible) single linked list implementation. However I am wondering what time complexity people expect of such a list?
Especially for inserting I am wondering how I should implement it. I've read some locations around the internet, where some say inserting is O(1) while others say O(n) - all agree that a double linked list is O(1). However I think O(1) is the case for single linked lists too?
As long as you know the preceding node you just let the preceding node point to the new new, and the new node will point towards where the preceding node did originally point to.
That said it makes me wonder how people expect insert to behave? Normally it inserts elements BEFORE the given iterator. However with a single-linked-list it is hard to do so (one would have to go through O(n) time to get the preceding element & then use above method). Is it common in such lists to make insert place items behind the current iterator? Or -probably better- is there another common function for this?
The complexity of the insertion depends on what you need to do. If you know preceding node (actually, a suitable handle to change the preceding node's "next pointer" is all you need), the complexity is O(1). If you need to find the location where to insert, the complexity is O(n).
With respect to the expectation, I would expect the insert() to behave the same as for doubly linked lists but I also realize that you can't achieve this: You either need to have a different time complexity (to find the predecessor node) or different iterator invalidation semantics (i.e., iterators to other nodes get invalidated). I think the C++ 2011 std::forward_list class template went for a different interface but retaining the guarantees on iterator validity.
To briefly explain why the iterator validity can be effected: An iterator doesn't have to only know about the current node. Instead, it could, for example, point to the predecessor's next pointer. When dereferencing the iterator, it would dereference first its pointer to the next pointer and then this pointer to get hold of the actual node. In return, it is possible to insert in front of the iterator because the iterator knows which next pointer to update. Unfortunately, this means that iterators may get invalidated because the pointer they point to may have changed and they would reference a different node (when erasing nodes, the iterator may have been moved to be entirely invalid although the node referenced is still there).

What is the best data structure for removing an element from the middle?

The data stucture must be like a stack. Only with one difference. I want to pop from any index not only last. When I have popped element n, the elements with indexes N > n must swap to N-1. Any ideas?
P.S.
Pushing element n into the last index of the stack.
Then popping it out.
Then deleting stack[n]
is a bad idea.
I think you're looking for a linked list.
A linked list (std::list) will allow you to remove an element from the middle with O(1) complexity and automatically "pull" up the elements after it. You can use a linked list like a stack by using push_front. However you need to be aware that accessing an element in a linked list is O(n) as you would need to start at the head of the list and then walk along the links from one element to the next until you have arrived at element n (so there is no O(1) indexing)
Basically you would need to
Create an iterator
advance it to position n
Get the element from the iterator
erase the element the iterator is currently pointing to
Some example code can be found here.
You need to implement a linked list, but unlike an array, the order in a linked list is determined by a pointer in each object. So, you cannot use indices to access the elements.

diff between ADT list and linked list

What is the ( real | significiant ) difference (s) between ADT list implementation and linked list implementation
with respect to queue ?
Moreover,
Can you suggest any website with visual example of these type of lists ?
It is REALLY hard to understand this question, but in an attempt to ask what the actual question is, I believe to have figured it out. So my assumption is, that the question is: "What is the difference between std::list and std::queue. #fatai: Please correct me, when I am wrong.
The std::list is a doubly-linked list. Each element of the list "knows" the next and previous element. And the list "knows" it's beginning and end. Look here: http://www.cplusplus.com/reference/stl/list/
The std::queue is a list, with special functionality. This functionality allows you to easily insert elements at the front, and remove elements from the back. Have a look here:
http://www.cplusplus.com/reference/stl/queue/
If you want to have minimal functionality, I'd use queue. The queue is optimized for its purpose. It also prevents you from doing things accidentally wrong (such as remove an element from the middle).
I hope that answers your (confusing) question. ;-)
Erasing and inserting into middle of the list by using iterator has O(n) complexity because in the background it has to shift all the other elements. (uses special model of vector ADT, but you cant even access to list element with index mechanism).
In linked-lists erasing and inserting to list has O(1) complexity. It doesn't needs to shift the elements for the operations. Even searching an element in linked lists has O(n) complexity like the list ADT.

Is time complexity for insertion/deletion in a doubly linked list of order O(n)?

To insert/delete a node with a particular value in DLL (doubly linked list) entire list need to be traversed to find the location hence these operations should be O(n).
If that's the case then how come STL list (most likely implemented using DLL) is able to provide these operations in constant time?
Thanks everyone for making it clear to me.
Insertion and deletion at a known position is O(1). However, finding that position is O(n), unless it is the head or tail of the list.
When we talk about insertion and deletion complexity, we generally assume we already know where that's going to occur.
It's not. The STL methods take an iterator to the position where insertion is to happen, so strictly speaking, they ARE O(1), because you're giving them the position. You still have to find the position yourself in O(n) however.
Deleting an arbitrary value (rather than a node) will indeed be O(n) as it will need to find the value. Deleting a node (i.e. when you start off knowing the node) is O(1).
Inserting based on the value - e.g. inserting in a sorted list - will be O(n). If you're inserting after or before an existing known node is O(1).
Inserting to the head or tail of the list will always be O(1) - because those are just special cases of the above.