Movatterモバイル変換


[0]ホーム

URL:


Jump to content
WikipediaThe Free Encyclopedia
Search

Queue (abstract data type)

From Wikipedia, the free encyclopedia
(Redirected fromQueue (data structure))
Abstract data type
This article includes a list ofgeneral references, butit lacks sufficient correspondinginline citations. Please help toimprove this article byintroducing more precise citations.(January 2014) (Learn how and when to remove this message)
Queue
Representation of aFIFO (first in, first out) queue
Time complexity inbig O notation
OperationAverageWorst case
SearchO(n)O(n)
InsertO(1)O(1)
DeleteO(1)O(1)
Space complexity
SpaceO(n)O(n)

Incomputer science, a queue is an abstract data type that serves as an orderedcollection of entities. By convention, the end of the queue where elements are added, is called the back, tail, or rear of the queue. The end of the queue where elements are removed is called the head or front of the queue. The namequeue is ananalogy to the words used to describe people in line to wait for goods or services. It supports two main operations.

  • Enqueue, which adds one element to the rear of the queue
  • Dequeue, which removes one element from the front of the queue.

Other operations may also be allowed, often including apeek orfront operation that returns the value of the next element to be dequeued without dequeuing it.

The operations of a queue make it afirst-in-first-out (FIFO) data structure as the first element added to the queue is the first one removed. This is equivalent to the requirement that once a new element is added, all elements that were added before have to be removed before the new element can be removed. A queue is an example of alinear data structure, or more abstractly a sequential collection.Queues are common in computer programs, where they are implemented as data structures coupled with access routines, as anabstract data structure or in object-oriented languages as classes. A queue may be implemented ascircular buffers andlinked lists, or by using both thestack pointer and the base pointer.

Queues provide services incomputer science,transport, andoperations research where various entities such as data, objects, persons, or events are stored and held to be processed later. In these contexts, the queue performs the function of abuffer.Another usage of queues is in the implementation ofbreadth-first search.

Queue implementation

[edit]

Theoretically, one characteristic of a queue is that it does not have a specific capacity. Regardless of how many elements are already contained, a new element can always be added. It can also be empty, at which point removing an element will be impossible until a new element has been added again.

Fixed-length arrays are limited in capacity, but it is not true that items need to be copied towards the head of the queue. The simple trick of turning the array into a closed circle and letting the head and tail drift around endlessly in that circle makes it unnecessary to ever move items stored in the array. If n is the size of the array, then computing indices modulo n will turn thearray into a circle. This is still the conceptually simplest way to construct a queue in ahigh-level language, but it does admittedly slow things down a little, because the array indices must be compared to zero and the array size, which is comparable to the time taken to check whether an array index is out of bounds, which some languages do, but this will certainly be the method of choice for a quick and dirty implementation, or for any high-level language that does not have pointer syntax. The array size must be declared ahead of time, but some implementations simply double the declared array size when overflow occurs. Most modern languages with objects orpointers can implement or come with libraries for dynamic lists. Suchdata structures may have not specified a fixed capacity limit besides memory constraints. Queueoverflow results from trying to add an element onto a full queue and queueunderflow happens when trying to remove an element from an empty queue.

Abounded queue is a queue limited to a fixed number of items.[1]

There are several efficient implementations of FIFO queues. An efficient implementation is one that can perform the operations—en-queuing and de-queuing—inO(1) time.

  • Linked list
    • Adoubly linked list has O(1) insertion and deletion at both ends, so it is a natural choice for queues.
    • A regular singly linked list only has efficient insertion and deletion at one end. However, a small modification—keeping a pointer to thelast node in addition to the first one—will enable it to implement an efficient queue.
  • Adeque implemented using a modified dynamic array

Queues and programming languages

[edit]

Queues may be implemented as a separate data type, or maybe considered a special case of adouble-ended queue (deque) and not implemented separately. For example,Perl andRuby allow pushing and popping an array from both ends, so one can usepush andshift functions to enqueue and dequeue a list (or, in reverse, one can useunshift andpop),[2] although in some cases these operations are not efficient.

C++'sStandard Template Library provides a "queue" templated class which is restricted to only push/pop operations. Since J2SE5.0, Java's library contains aQueue interface that specifies queue operations; implementing classes includeLinkedList and (since J2SE 1.6)ArrayDeque. PHP has anSplQueue class and third-party libraries likebeanstalk'd andGearman.

UML queue class.svg

Example

[edit]

A simple queue implemented inJavaScript:

classQueue{constructor(){this.items=[];}enqueue(element){this.items.push(element);}dequeue(){returnthis.items.shift();}}

Purely functional implementation

[edit]

Queues can also be implemented as apurely functional data structure.[3] There are two implementations. The first one only achievesO(1){\displaystyle O(1)} per operationon average. That is, theamortized time isO(1){\displaystyle O(1)}, but individual operations can takeO(n){\displaystyle O(n)} wheren is the number of elements in the queue. The second implementation is called areal-time queue[4] and it allows the queue to bepersistent with operations in O(1) worst-case time. It is a more complex implementation and requireslazy lists withmemoization.

Amortized queue

[edit]

This queue's data is stored in twosingly-linked lists namedf{\displaystyle f} andr{\displaystyle r}. The listf{\displaystyle f} holds the front part of the queue. The listr{\displaystyle r} holds the remaining elements (a.k.a., the rear of the queue)in reverse order. It is easy to insert into the front of the queue by adding a node at the head off{\displaystyle f}. And, ifr{\displaystyle r} is not empty, it is easy to remove from the end of the queue by removing the node at the head ofr{\displaystyle r}. Whenr{\displaystyle r} is empty, the listf{\displaystyle f} is reversed and assigned tor{\displaystyle r} and then the head ofr{\displaystyle r} is removed.

The insert ("enqueue") always takesO(1){\displaystyle O(1)} time. The removal ("dequeue") takesO(1){\displaystyle O(1)} when the listr{\displaystyle r} is not empty. Whenr{\displaystyle r} is empty, the reverse takesO(n){\displaystyle O(n)} wheren{\displaystyle n} is the number of elements inf{\displaystyle f}. But, we can say it isO(1){\displaystyle O(1)}amortized time, because every element inf{\displaystyle f} had to be inserted and we can assign a constant cost for each element in the reverse to when it was inserted.

Real-time queue

[edit]

The real-time queue achievesO(1){\displaystyle O(1)} time for all operations, without amortization. This discussion will be technical, so recall that, forl{\displaystyle l} a list,|l|{\displaystyle |l|} denotes its length, thatNIL represents an empty list andCONS(h,t){\displaystyle \operatorname {CONS} (h,t)} represents the list whose head ish and whose tail ist.

The data structure used to implement our queues consists of threesingly-linked lists(f,r,s){\displaystyle (f,r,s)} wheref is the front of the queue andr is the rear of the queue in reverse order. The invariant of the structure is thats is the rear off without its|r|{\displaystyle |r|} first elements, that is|s|=|f||r|{\displaystyle |s|=|f|-|r|}. The tail of the queue(CONS(x,f),r,s){\displaystyle (\operatorname {CONS} (x,f),r,s)} is then almost(f,r,s){\displaystyle (f,r,s)} andinserting an elementx to(f,r,s){\displaystyle (f,r,s)} is almost(f,CONS(x,r),s){\displaystyle (f,\operatorname {CONS} (x,r),s)}. It is said almost, because in both of those results,|s|=|f||r|+1{\displaystyle |s|=|f|-|r|+1}. An auxiliary functionaux{\displaystyle aux} must then be called for the invariant to be satisfied. Two cases must be considered, depending on whethers{\displaystyle s} is the empty list, in which case|r|=|f|+1{\displaystyle |r|=|f|+1}, or not. The formal definition isaux(f,r,Cons(_,s))=(f,r,s){\displaystyle \operatorname {aux} (f,r,\operatorname {Cons} (\_,s))=(f,r,s)} andaux(f,r,NIL)=(f,NIL,f){\displaystyle \operatorname {aux} (f,r,{\text{NIL}})=(f',{\text{NIL}},f')} wheref{\displaystyle f'} isf followed byr reversed.

Let us callreverse(f,r){\displaystyle \operatorname {reverse} (f,r)} the function which returnsf followed byr reversed. Let us furthermore assume that|r|=|f|+1{\displaystyle |r|=|f|+1}, since it is the case when this function is called. More precisely, we define a lazy functionrotate(f,r,a){\displaystyle \operatorname {rotate} (f,r,a)} which takes as input three lists such that|r|=|f|+1{\displaystyle |r|=|f|+1}, and return the concatenation off, ofr reversed and ofa. Thenreverse(f,r)=rotate(f,r,NIL){\displaystyle \operatorname {reverse} (f,r)=\operatorname {rotate} (f,r,{\text{NIL}})}.The inductive definition of rotate isrotate(NIL,Cons(y,NIL),a)=Cons(y,a){\displaystyle \operatorname {rotate} ({\text{NIL}},\operatorname {Cons} (y,{\text{NIL}}),a)=\operatorname {Cons} (y,a)} androtate(CONS(x,f),CONS(y,r),a)=Cons(x,rotate(f,r,CONS(y,a))){\displaystyle \operatorname {rotate} (\operatorname {CONS} (x,f),\operatorname {CONS} (y,r),a)=\operatorname {Cons} (x,\operatorname {rotate} (f,r,\operatorname {CONS} (y,a)))}. Its running time isO(r){\displaystyle O(r)}, but, since lazy evaluation is used, the computation is delayed until the results are forced by the computation.

The lists in the data structure has two purposes. This list serves as a counter for|f||r|{\displaystyle |f|-|r|}, indeed,|f|=|r|{\displaystyle |f|=|r|} if and only ifs is the empty list. This counter allows us to ensure that the rear is never longer than the front list. Furthermore, usings, which is a tail off, forces the computation of a part of the (lazy) listf during eachtail andinsert operation. Therefore, when|f|=|r|{\displaystyle |f|=|r|}, the listf is totally forced. If it was not the case, the internal representation off could be some append of append of... of append, and forcing would not be a constant time operation anymore.

See also

[edit]

References

[edit]
  1. ^"Queue (Java Platform SE 7)". Docs.oracle.com. 2014-03-26. Retrieved2014-05-22.
  2. ^"Class Array".
  3. ^Okasaki, Chris."Purely Functional Data Structures"(PDF).
  4. ^Hood, Robert; Melville, Robert (November 1981). "Real-time queue operations in pure Lisp".Information Processing Letters.13 (2):50–54.doi:10.1016/0020-0190(81)90030-2.hdl:1813/6273.

General references

[edit]

Further reading

[edit]

External links

[edit]
Wikimedia Commons has media related toQueue data structure.
Types
Abstract
Arrays
Linked
Trees
Graphs
Retrieved from "https://en.wikipedia.org/w/index.php?title=Queue_(abstract_data_type)&oldid=1320062264"
Category:
Hidden categories:

[8]ページ先頭

©2009-2025 Movatter.jp