Constant time to access first and last node - data-structures

How would you modify a linked list based queue so that first and last node can be accessed in a constant time regardless of data nodes in queue?

You will keep two pointers/reference variables, one for head of queue and other for tail. When you insert an item, you will set the tail to last inserted item, and when you remove an item, your head will obviously go to next item in queue. Since you have two variables for head and tail, it will be a constant time operation to access them.
This is the general way to create a queue with linked list itself, this will be needed to insert items and remove items from queue, nothing special here.

Related

What is the difference between linkedlist and queue?

I'm new to data structures and it seems like both data structures have more similarities.
In this answer it says that there is a difference in interface.
Please explain it.
A queue is any data structure that is "FIFO = First-In First-Out." It's a waiting-list. (In Britain, the term is used in ordinary conversation ... you "wait in a queue" not "wait in line.")
A stack is any data structure that is "LIFO = Last-In First-Out." It's a pushdown stack like the stack of dishes in a cafeteria.
Linked lists are a possible implementation of either such structure. It consists of nodes which contain pointers to adjacent nodes in the list.
However, there are many other implementations. "Trees" of various kinds can also be used to implement both queues and stacks. Ordinary arrays can do it, although of course arrays cannot "grow."
Ideally, these days, you simply use an appropriate "container class" in your favorite language and fuhgeddabout how it actually was implemented. "You know that it works, therefore you don't care how." Actual implementation of such things is probably an academic exercise.
List is just a list of things (items, objects whatever). For example a list of courses you are taking in your semester. A list of songs that you are listening. A list of answers of this question on this page. There is no order associate with a list. You can add an item to a list anywhere, you can take an item off the list from anywhere, it doesn't change the definition of a list. Its just a grouping of similar (or not so similar) items.
Now consider a list of people standing in front of ATM machine or a bank teller. This list has to observe a particular order. The first person in the line (list) is the one that will be served first (and will be the first to leave this list). A new person coming in will be standing as a last person in the queue and will be served after everyone in front of him has been served. The people in middle of the list are not supposed to jump the line. This is an example of a Queue. You can also guess what a priority Queue would be (think Airlines with silver and gold members on check-ins).
I hope this explains the difference.
A link list is a list of nodes. Each node contain an address field and that address field holding the address of its next node. The reason for this kind of structure is to traverse through the list from its first node till last node. This type of structure is called singly link list. A link list can also be doubly linked, in that structure a node will have two address field where one field will store the address of its previous node and one address will hold the address of its next node. Most important thing of a link list is that its first node address must be stored in an address variable so that we can traverse through the link list at any time.
But Queue can be a link list or an array of nodes. In a list a node can be insert at any place. But in queue a new node must be inserted at the beginning of the list. A queue is working on basis of FIFO i.e. first in first out basis. Hence when you use the pop command on a queue if it is a link list it must remove the last node of the list and return the value of that last node. Hence a queue can be a list as well but with a principle called FIFO based.
You will get more information online. Read properly and try to understand the difference.
I had the same question as you! This is what I found:
A Queue is essentially just more restrictive than a LinkedList. For example, in a LinkedList you can use the method .add(int index, Object obj), but if you try doing that with a Queue interface, you’ll get an error, since with a Queue you can only add elements at the tail end. Similarly, in a LinkedList you can use .remove(int index) as well as .remove(Object obj), but attempting to do this with a Queue will result in an error, since you can only remove an object from the head. So, in essence, the Queue just has less options when it comes to methods you can use on it. (There might be more to it than that, but that’s what was most pertinent to me.)
There are some similarities between the two. For example, they both have the .poll() method, and the result is the same: removes the head element from the Object.
Here are some links in which you can compare the methods of the two (scroll to the bottom of each page to see them all, and you’ll see immediately that LinkedList has a lot more):
https://www.geeksforgeeks.org/linked-list-in-java/ (LinkedList)
https://www.geeksforgeeks.org/queue-interface-java/ (Queue)
In Java (and probably other languages too), a LinkedList implements the Queue interface. So in essence, a LinkedList is a Queue; it has all features that a Queue does and more. Keep in mind, a Queue is not a LinkedList, as a LinkedList is built and expanded upon a Queue.
See this:

How to implement a collection that supports real-time filtering?

I want to implement a mutable sequential collection FilteredList that wraps another collection List and filters it based on a predicate.
Both the wrapped List and the exposed FilteredList are mutable and observable, and should be synchronized (so for example, if someone adds an element to List that element should appear in the correct position in FilteredList, and vice versa).
Elements that don't satisfy the predicate can still be added to FilteredList, but they will not be visible (they will still appear in the inner list).
The collections should support:
Insert(index,value) which inserts an element value at position index, pushing elements forward.
Remove(index) which removes the element at position index, moving all proceeding elements back.
Update(index, value), which updates the element at position index to be value.
I'm having trouble coming up with a good synchronization mechanism.
I don't have any strict complexity bounds, but real world efficiency is important.
The best way to avoid synchronization difficulties is to create a data structure that doesn't need them: use a single data structure to present the filtered and unfiltered data.
You should be able to do that with a modified skip list (actually, an indexable skip list), which will give you O(log n) access by index.
What you do is maintain two separate sets of forward pointers for each node, rather than just one set. The one set is for the unfiltered list, as in the normal skip list, and the other set is for the filtered list.
Adding to or removing from the list is the same for the filtered and unfiltered lists. That is, you find the node at index by following the appropriate filtered or unfiltered links, and then add or remove the node, updating both sets of link pointers.
This should be more efficient than a standard sequential list, because insertion and removal don't incur the cost of moving items up or down to make a hole or fill a gap; it's all done with references.
It takes a little more space per node, though. On average, skip list requires two extra references per node. Since you're building what is in effect two skip lists in one, expect your nodes to require, on average, four extra references per node.
Edit after comment
If, as you say, you don't control List, then you still maintain this dual skip list that I described. But the data stored in the skip list is just the index into List. You said that List is observable, so you get notification of all insert and delete operations, so you should be able to maintain an index by reacting to all notifications.
When somebody wants to operate on FilteredList, you use the filtered index links to find the List index of the FilteredList record the user wanted to affect. Then you pass the request onto List, using the translated index. And then you react to the observable notification from List.
Basically, you're just maintaining a secondary index into List, so that you can translate FilteredList indexes into List indexes.

why do we make head a null in singly linked list?

Why is that when we try to make a singly linked list we make the Head NULL in the class and not make the Next of the Head as Null . In the functions regarding the linked lists why do we make the Next of the nodes Null and not make the Node Null?
To avoid waste. A list node is designed to store an element inside of it. Imagine if we had an empty list in your suggested scenario, where * denotes the head of the list. We would start with:
[*???]->NULL
Where ??? would just be some dummy variable for an unused element. We're already wasting a list node when we could simply do this:
*NULL
Likewise if we examine a non-empty list, we might have with your case:
[*123]->[456]->[789]->[???]->NULL
... when we could simply have:
[*123]->[456]->[789]->NULL
Of course you could augment this to overwrite this dummy variable when the list size goes from 0 to 1, but now that involves additional branching and so forth and we end up getting more complex instructions and processing overhead.
So there's really little to be gained by doing this, and potentially a lot to be lost.
In the functions regarding the linked lists why do we make the Next of
the nodes Null and not make the Node Null?
I didn't quite understand this part. If we're talking about inserting a new node to a list, for example, we might have this:
[new node: 456]->??? [*123]->NULL
We then make it point to the head:
[new node: 456]->[*123]->NULL
... and then make the head point to the new node.
[*456]->[123]->NULL
So there should typically not be times where you're setting the next pointer of a node to null, unless it's to the head which happens to be null, or in response to removing a tail.

how to store and delete sorted items in a file

I am trying to store elements in a file in a sorted order.
The elements will be in the following format:
1 MessageA
2 MessageB
.
.
54 MessageM
68 MessageN
Each element will have a number(timestamp) & a message(size is variable).
The elements must be sorted by timestamp.
Operation allowed are insert and delete(Pop).
(Growing file size is not an issue)
and we can delete only from the lower most element(i.e. delete one after another).
Currently I have implemented it as a linked list which is very slow on inserts when the number of elements are large.
what will be the most efficient data structure to store this?
I'm not sure if you want to delete the oldest or the newest element but you should probably look into stacks and queues.
Stacks are First In Last Out, meaning that the element inserted first will be deleted (popped) last, as it would happen with a real stack, hence the name. Here the popped element would be the newest.
Queues are First In First Out. Here the deleted element (dequeued) is the oldest still present in the queue.

Implement a queue which keeps non-decreasing

As everyone knows, a standard queue supports two basic operations: insert and popout. And insert occurs at the tail of the queue, while popout occurs at the head of the queue. Here, I have no idea whether I can keep this queue ordered, like non-decreasing, based on this two operations, or perhaps with some additional help functions to achieve that goal?
You just have to change insert function a little. Every time you insert into the queue you have to find the new element place in the queue it could be achieved with following algorithm:
Use a recursive function and every time check if your new element is greater than the element in the middle of the list, if not, try to insert new element in left side of queue else try to insert in the right side of queue, do it recursively until you find the proper place for the element.
Thin algorithm for insert is O(lg(n)).
For popout you could just do what you are done now, popout the last element.

Resources