Why Q.head = Q.tail + 1 represents the queue is full in CLRS

人盡茶涼 提交于 2020-05-29 02:38:12

问题


I was reading Elementary Data Structures from CLRS and while reading Queue ADT I came across this:

When Q.head = Q.tail + 1 , the queue is full, and if we attempt to enqueue an element, then the queue overflows.

Is it always true? because if Q.tail equals Q.length then we set Q.tail = 1 according to the text. Therefore if we completely fill the Queue then Q.tail and Q.head will be pointing to the same position (index 1) and the above condition shall not hold. What am I missing here? Please point out where am I misinterpreting the text. Thanks in advance.

Here Attribute Q.head indexes, or points to, queue's head. The attribute Q.tail indexes the next location at which a newly arriving element will be inserted into the queue.


回答1:


Wrap around feature of queue:

You need to understand the fact that location 1 in the array immediately follows location n in circular order. For example enter image description here

Predecessor of element g at index 1 is f at index 11. Tail pointer always points to the next empty location where new element will be inserted, in enqueue operation, before inserting element we check for overflow condition, if Q.tail +1 = Q.head, it means tail is reached at head location, means no free space, means queue is full.

NOTE: (n-1) length queue can be created with the array of length n.




回答2:


As mentioned in the same paragraph in CLRS,

to implement a queue of at most n-1 elements using an array Q[1...n].

which means one position is left. It's for checking if the queue is full. If we use all the array positions, the empty queue condition and full queue condition would be the same, which is Q.head=Q.tail. @siddstuff has explained the wrap around feature, Q.head = Q.tail+1 means there is only one empty position left, so the queue is full.




回答3:


I don't have your book, but from how I would implement a cyclic buffer: The condition head = tail + 1 means that if an element is inserted then tail is increased by one and then tail = head. But if head is equal to tail the queue is considered empty.




回答4:


Just to clarify, the reason you can't allow the array to be completely filled is because then there would be no way to determine if it's full or empty.

To check if it's empty Q.head = Q.tails is the only way, for you can't rely on something like Q.head = 1 and Q.tails = 1 since the queue could be empty in any position, not just position 1.

That's the reason a queue created with an array of length n can only hold up to n-1 elements, and to check if it's full we do Q.tail + 1 = Q.head (or (Q.tail + 1) mod n to account for the case where Q.tail points at position n).




回答5:


It's been been six years but none of these answers point out the fact that in circular buffers, there is no clean way to differentiate the case where the buffer full vs empty cases. In both cases head = tail.

Most workarounds hinder readability and introduce complexities, so when implementing circular buffers, we make a few assumptions that solve this problem and maintain simplicity.

  • We deliberately use only N-1 elements in the N element buffer.
  • When head = tail it means the buffer empty.
  • tail + 1 = head means the buffer full.

Here is a good read on implementing circular buffers.




回答6:


When the queue is implemented with an array of Q[1..n], It can hold up to n-1 elements. But the condition for is_full must be [head == tail+1] mod n not just head == tail+1.



来源:https://stackoverflow.com/questions/16395354/why-q-head-q-tail-1-represents-the-queue-is-full-in-clrs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!