What is the purpose of maintaining rear in a dynamic queue? - queue

It is understood why we need to maintain a rear in static queue but why is it necessary to maintain a rear in the dynamic queue, I understand that it makes the programming easier and reduces the time complexity(b/c lesser loops are required)
but then we should maintain a rear in the singly linked list as well.

One of the operations of a queue is adding an element to the end (rear) of the queue: The enqueue operation. Maintaining a reference to the rear of the queue allows implementing the enqueue operation in constant time (although, other sources of complexity may exist depending on the type of the lower level data structure used as the basis of the queue).
I understand that it makes the programming easier and reduces the time complexity ... but then we should maintain a rear in the singly linked list as well.
Singly linked list does not need to provide an enqueue operation, so maintaining a rear-pointer is not necessary.
However, it is possible to augment a singly linked list with a rear pointer if it is desired.

It is understood why we need to maintain a rear in static queue but
why is it necessary to maintain a rear in the dynamic queue
By the same reason. New elements are added to one side and old elements are pooped from other side by the definition of the notion of queue.
...but then we should maintain a rear in the singly linked list as well.
There is no logical relation between a queue and a singly-linked list. A queue can be implemented by any underlined container that supports the push and pop operations from opposite sides.
If you want to use a singly-linked list as the underlined container then indeed you should to use a two-sided singly-linked list to make the operations more efficient.
One-sided singly linked list is more appropriate to simulate a stack than a queue.

Related

Doubly linked list of process control block in Operating Systems

What is the reasoning behind maintaining doubly linked lists of PCB's(process control blocks) in an OS for scheduling. I have seen this mentioned multiple times for Real time operating systems.
I would ideally go for a circular singly linked list , so that you could do a round robin and reach back to 1st task after looking to all. You could also sort it by priority...
But, why a doubly linked list?
You have made the assumption that you would always want to start at the head, and work towards the end of the list. This may not be true. Say you are swapping one process out (eg it is pending on a sempahore). You already have the current process control block, so it makes sense to start using the information you have rather than iterate through the entire list.
Because the PCB has a reference to both the previous and the next, you can cut that node out of the running-list, and move to a pended-list, or from a pended-list back into a ready-to-run list etc, without having to iterate all the way through.

How to handle the two signals depending on each other?

I read Deprecating the Observer Pattern with Scala.React and found reactive programming very interesting.
But there is a point I can't figure out: the author described the signals as the nodes in a DAG(Directed acyclic graph). Then what if you have two signals(or event sources, or models, w/e) depending on each other? i.e. the 'two-way binding', like a model and a view in web front-end programming.
Sometimes it's just inevitable because the user can change view, and the back-end(asynchronous request, for example) can change model, and you hope the other side to reflect the change immediately.
The loop dependencies in a reactive programming language can be handled with a variety of semantics. The one that appears to have been chosen in scala.React is that of synchronous reactive languages and specifically that of Esterel. You can have a good explanation of this semantics and its alternatives in the paper "The synchronous languages 12 years later" by Benveniste, A. ; Caspi, P. ; Edwards, S.A. ; Halbwachs, N. ; Le Guernic, P. ; de Simone, R. and available at http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1173191&tag=1 or http://virtualhost.cs.columbia.edu/~sedwards/papers/benveniste2003synchronous.pdf.
Replying #Matt Carkci here, because a comment wouldn't suffice
In the paper section 7.1 Change Propagation you have
Our change propagation implementation uses a push-based approach based on a topologically ordered dependency graph. When a propagation turn starts, the propagator puts all nodes that have been invalidated since the last turn into a priority queue which is sorted according to the topological order, briefly level, of the nodes. The propagator dequeues the node on the lowest level and validates it, potentially changing its state and putting its dependent nodes, which are on greater levels, on the queue. The propagator repeats this step until the queue is empty, always keeping track of the current level, which becomes important for level mismatches below. For correctly ordered graphs, this process monotonically proceeds to greater levels, thus ensuring data consistency, i.e., the absence of glitches.
and later at section 7.6 Level Mismatch
We therefore need to prepare for an opaque node n to access another node that is on a higher topological level. Every node that is read from during n’s evaluation, first checks whether the current propagation level which is maintained by the propagator is greater than the node’s level. If it is, it proceed as usual, otherwise it throws a level mismatch exception containing a reference to itself, which is caught only in the main propagation loop. The propagator then hoists n by first changing its level to a level above the node which threw the exception, reinserting n into the propagation queue (since it’s level has changed) for later evaluation in the same turn and then transitively hoisting all of n’s dependents.
While there's no mention about any topological constraint (cyclic vs acyclic), something is not clear. (at least to me)
First arises the question of how is the topological order defined.
And then the implementation suggests that mutually dependent nodes would loop forever in the evaluation through the exception mechanism explained above.
What do you think?
After scanning the paper, I can't find where they mention that it must be acyclic. There's nothing stopping you from creating cyclic graphs in dataflow/reactive programming. Acyclic graphs only allow you to create Pipeline Dataflow (e.g. Unix command line pipes).
Feedback and cycles are a very powerful mechanism in dataflow. Without them you are restricted to the types of programs you can create. Take a look at Flow-Based Programming - Loop-Type Networks.
Edit after second post by pagoda_5b
One statement in the paper made me take notice...
For correctly ordered graphs, this process
monotonically proceeds to greater levels, thus ensuring data
consistency, i.e., the absence of glitches.
To me that says that loops are not allowed within the Scala.React framework. A cycle between two nodes would seem to cause the system to continually try to raise the level of both nodes forever.
But that doesn't mean that you have to encode the loops within their framework. It could be possible to have have one path from the item you want to observe and then another, separate, path back to the GUI.
To me, it always seems that too much emphasis is placed on a programming system completing and giving one answer. Loops make it difficult to determine when to terminate. Libraries that use the term "reactive" tend to subscribe to this thought process. But that is just a result of the Von Neumann architecture of computers... a focus of solving an equation and returning the answer. Libraries that shy away from loops seem to be worried about program termination.
Dataflow doesn't require a program to have one right answer or ever terminate. The answer is the answer at this moment of time due to the inputs at this moment. Feedback and loops are expected if not required. A dataflow system is basically just a big loop that constantly passes data between nodes. To terminate it, you just stop it.
Dataflow doesn't have to be so complicated. It is just a very different way to think about programming. I suggest you look at J. Paul Morison's book "Flow Based Programming" for a field tested version of dataflow or my book (once it's done).
Check your MVC knowledge. The view doesn't update the model, so it won't send signals to it. The controller updates the model. For a C/F converter, you would have two controllers (one for the F control, on for the C control). Both controllers would send signals to a single model (which stores the only real temperature, Kelvin, in a lossless format). The model sends signals to two separate views (one for C view, one for F view). No cycles.
Based on the answer from #pagoda_5b, I'd say that you are likely allowed to have cycles (7.6 should handle it, at the cost of performance) but you must guarantee that there is no infinite regress. For example, you could have the controllers also receive signals from the model, as long as you guaranteed that receipt of said signal never caused a signal to be sent back to the model.
I think the above is a good description, but it uses the word "signal" in a non-FRP style. "Signals" in the above are really messages. If the description in 7.1 is correct and complete, loops in the signal graph would always cause infinite regress as processing the dependents of a node would cause the node to be processed and vice-versa, ad inf.
As #Matt Carkci said, there are FRP frameworks that allow loops, at least to a limited extent. They will either not be push-based, use non-strictness in interesting ways, enforce monotonicity, or introduce "artificial" delays so that when the signal graph is expanded on the temporal dimension (turning it into a value graph) the cycles disappear.

Why no immutable double linked list in Scala collections?

Looking at this question, where the questioner is interested in the first and last instances of some element in a List, it seems a more efficient solution would be to use a DoubleLinkedList that could search backwards from the end of the list. However there is only one implementation in the collections API and it's mutable.
Why is there no immutable version?
Because you would have to copy the whole list each time you want to make a change. With a normal linked list, you can at least prepend to the list without having to copy everything. And if you do want to copy everything on every change, you don't need a linked list for that. You can just use an immutable array.
There are many impediments to such a structure, but one is very pressing: a doubly linked list cannot be persistent.
The logic behind this is pretty simple: from any node on the list, you can reach any other node. So, if I added an element X to this list DL, and tried to use a part of DL, I'd face this contradiction: from the node pointing to X one can reach every element in part(DL), but, by the properties of the doubly linked list, that means from any element of part(DL) I can reach the node pointing to X. Since part(DL) is supposed to be immutable and part of DL, and since DL did not include the node pointing to X, that just cannot be.
Non-persistent immutable data structures might have some uses, but they are generally bad for most operations, since they need to be recreated whenever a derivative is produced.
Now, there's the minor matter of creating mutually referencing strict objects, but this is surmountable. One can use by-name parameters and lazy vals, or one can do like Scala's List: actually create a mutable collection, and then "freeze" it in immutable state (see ListBuffer and it's toList method).
Because it is logically impossible to create a mutually (circular) referential data-structure with strict immutability.
You cannot create two nodes that point to each other due to simple existential ordering priority, in that at least one of the nodes will not exist when the other is created.
It is possible to get this circularity with tricks involving laziness (which is implemented with mutation), but the real question then becomes why you would want this thing in the first place?
As others have noted, there is no persistent implementation of a double-linked list. You will need some kind of tree to get close to the characteristics you want.
In particular, you may want to look at finger trees, which provide O(1) access to the front and back, amortized O(1) insertion to the front and back, and O(log n) insertion elsewhere. (That's in contrast to most other commonly-used trees which have O(log n) access and insertion everywhere.)
See also:
video explanation of finger trees (by the implementor of finger trees in clojure.contrib)
finger tree implementation in Scala (I haven't used it personally, but it's the top google hit)
As a supplemental to the answer of #KimStebel I like to add:
If you are searching for a data structure suitable for the question that motivated you to ask this question, then you might have a look at Extreme Cleverness: Functional Data Structures in Scala by #DanielSpiewak.

Is it possible to have two priority queues "in sync" in Scala?

I have a set of objects with two kinds of priorities.
I can create two PriorityQueues ordered by each of them.
The problem is that when I dequeue element from one of them it will obviously not disappear from the other one.
Is it possible to create 2 queues "in sync", so that when element is removed from one then it will be removed from the other?
This warrants a special kind of a data structure. The standard "binary heap under the hood" priority queue available in the standard library cannot do the trick, because it doesn't know "where" in the other binary heap the required element is.
A similar problem happens when you try to implement Dijkstra's algorithm or A*. The trick that works there is to use 2 ordered trees as if they were queues - you can pop the first element, and you can then search for it in the other tree.
If you do not need logarithmic operations, just use double linked list as queues. They do not guarentee FIFO but provide what you need.
You can easily wrap two of those in one class.

is breadth first search or breadth first traversal possible without using a queue?

As I remember and checked, the usual way for traversing a tree or crawling the web breadth first (BFS) is by using a queue. Is there actually a way to implement it not using a queue?
I know this question is old now, but I just wanted to answer. You can do this with arrays, linked lists (or any other linear container) and without recursion. Keep two containers, old and new, and swap old with new when you traverse all of the items in old. Very similar to the implementation with queue.
In Python it would look like:
def breadth_first(root):
if not root:
return
old = []
new = []
old.append(root)
while old:
for n in old:
process(n) # Do something
if n.left:
new.append(n.left)
if n.right:
new.append(n.right)
old = new
new = []
Runtime complexity would be the same as the queue implementation, O(n).
You really should be using a queue, as its easier to implement. Also, a queue allows for multiple machines to work together (one queues site while another pops sites off of the queue to traverse).
The only other way I see to do this is by using recursion (much more difficult, and uses only marginally either more or less memory).
With recursion. But the queue is in the stack...
if you care about ordering, use queue. queue preserves the insertion ordering. or you can use list's implementation, say, two array lists, to alternate. But fundamentally, list preserves ordering too.
if you don't care about ordering, you can use any set implementations. sets doesn't preserve this ordering.
For example, in BFS implementation, if you don't care the ordering of nodes, you can use two sets, old and new to alternate, rather than a queue.