1 / 17

Chapter 6 – Queues and Deques

6.4 The Deque 6.5 Simulating Waiting Lines Using Queues. Chapter 6 – Queues and Deques. Attendance Quiz #20. Tip #21: Constness. What does it mean for a member function to be const? Bitwise constness (also known as physical constness ).

desmondk
Download Presentation

Chapter 6 – Queues and Deques

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 6.4 The Deque 6.5 Simulating Waiting Lines Using Queues Chapter 6 – Queues and Deques

  2. Attendance Quiz #20 Queues / Deques (21)

  3. Tip #21: Constness Queues / Deques (21) • What does it mean for a member function to be const? • Bitwise constness (also known as physical constness). • A member function is const if and only if it doesn't modify any of the object's data members (excluding static members.) • Easy for the compiler to detect violations - just look for assignments to data members. • Logical constness. • A member function that modifies what a pointer points to is bitwise constness but not logical constness. • Sometimes there is requirement to modify one or more data members of class/struct by a const function even though you don’t want the function to update other members of class. • The solution is simple: take advantage of C++'s const-related wiggle room storage class specifier know as mutable. • Adding the keyword mutable before an object variable declaration allows a const function to change the object member.

  4. Reporting Expression Errors Queues / Deques (21) Expression: 3 $ 3 Infix: Illegal Operator at 2 Expression: - Infix: Missing Operand at 1 Expression: 21 + Infix: Missing Operand at 3 Expression: + 7 1 Infix: Missing Operand at 1 Expression: 4 % 2 5 - Infix: Missing Operator at 4 Expression: 43 + 2 * 19 + Infix: Missing Operand at 7 Expression: ( 43 + + 2 * 19 Infix: Unbalanced at 1 Expression: ( 43 + + 2 ) * 19 20 Infix: Missing Operand at 4 Expression: { { 2 + 4 } Infix: Unbalanced at 7 Expression: 3 % { 7 - ( 2 / [ 5 - 81 ] } + 1 ) Infix: Unbalanced at 14 1st Check for Balance 2nd Return 1st occurrence of an error.

  5. 6.4 The Deque Specification of the Deque Implementing the Deque Using a Circular Array The Standard Library Implementation of the Deque 6.4, pgs. 376-380

  6. Deque ADT Queues / Deques (21) • A deque(double-ended queue) is an abstract data type that generalizes a queue, for which elements can be added to or removed from either the front (head) or back (tail). • A dequediffers from the queue abstract data type or First-In-First-Out List (FIFO), where elements can only be added to one end (EIEO). • Restricted dequesare of two types: • An input-restricted deque (IRDeque) is one where deletion can be made from both ends, but insertion can be made at one end only. • An output-restricted deque (ORDeque) is one where insertion can be made at both ends, but deletion can be made from one end only. • The C++ standard library defines the class std::dequeto be a sequence that, like the std::vector, that supports random-access iterators (not supported by either the stackor the queue) in addition to constant-time insertion and removal from either end.

  7. Specification of the Deque Queues / Deques (21)

  8. STL Implementation of the Deque Queues / Deques (21) • There are at least three common ways to efficiently implement a deque: • A doubly linked list. • A circular array. • A modified dynamic array. • The modified dynamic array approach uses a variant of a dynamic array that can grow from both ends, sometimes called array deques. • These array deques have all the properties of a dynamic array, • constant-time random access, • good locality of reference, • inefficient insertion/removal in the middle, • And with the addition of amortized constant-time insertion/removal at both ends, instead of just one end.

  9. STL Implementation of the Deque Queues / Deques (21) • Efficient array implementations of a deque: • Store the deque contents in a common circular buffer, and only resize when the buffer becomes full. • This decreases the frequency of resizings. • Allocate deque contents from the center of the underlying array and resize the underlying array when either end is reached. • This approach may require more frequent resizings and waste more space, particularly when elements are only inserted at one end. • Store contents in multiple smaller arrays, allocating additional arrays at the beginning or end as needed. • Indexing is implemented by keeping a dynamic array containing pointers to each of the smaller arrays.

  10. Circular Array Deque Queues / Deques (21) • CArray class supports arrays that are like C arrays, but can dynamically shrink and grow as necessary. • A specialization of a CArray is part of the standard deque implementation. • A circular array makes random access straight forward: /** Returns a reference to an item in the deque. */ Item_Type& operator[](size_ti) { return the_data[(i + front_index) % capacity]; }

  11. Dynamic Circular Array Deque Queues / Deques (21) • The standard library implementation circular array contains pointers to fixed-size, dynamically allocated arrays that contain the data. • The first data item is located at offset. • The last data item is located at index (offset + num_items – 1) % BLOCK_SIZE in the last data block.

  12. STL Implementation of the Deque Queues / Deques (21) • The original designers chose this rather elaborate implementation rather than simply using a circular array because of the cost of reallocation. • Even though we amortize the cost of the reallocation so that each push_front or push_back is a constant-time operation, the reallocation can take a significant amount of time. • Storing pointers to single objects in the circular array could work, but dynamically allocating small/single objects has a significant space overhead. • By storing only pointers in the circular array, the cost of reallocation is significantly reduced, because copying a pointer is a simple operation. • Thus, by allocating an array of objects, we minimize this space overhead and minimize the cost of the reallocation. • For large collections of large objects, the dequecan be used instead of the vector to minimize space overhead and the cost of reallocation.

  13. The Data Fields for the Deque Queues / Deques (21) /** Returns a reference to an item referenced by an index. @parami the index @return A reference to deque[i] */ template<typenameItem_Type> Item_Type& deque<Item_Type>::operator[](size_ti) { if (i >= num_items) throw std::out_of_range("Invalid index deque::operator[]"); size_tblock_index = (offset + i) / BLOCK_SIZE; size_tdata_index = (offset + i) % BLOCK_SIZE; return the_data[block_index][data_index]; }

  14. The push_back Function Queues / Deques (21) /** Pushes an item onto the back of the deque. @param item The item to be inserted. */ template<typenameItem_Type> void deque<Item_Type>::push_back(const Item_Type& item) { size_t capacity = the_data.size() * BLOCK_SIZE; // Determine if the capacity needs to be increased. if ((num_items + offset) == capacity) { the_data.push_back(new Item_Type[BLOCK_SIZE]); } // Use index operator to insert item num_items++; (*this)[num_items - 1] = item; }

  15. The pop_front Function Queues / Deques (21) /** Removes the front item from the deque. */ template<typenameItem_Type> void deque<Item_Type>::pop_front() { offset++; if (offset == BLOCK_SIZE) { delete[] the_data.front(); the_data.pop_front(); offset = 0; } num_items--; }

  16. /** Returns a reference to an item referenced by an index. @parami the index @return A reference to deque[i] */ template<typenameItem_Type> Item_Type& deque<Item_Type>::operator[](size_ti) { size_t block_index = (offset + i) / BLOCK_SIZE; size_tdata_index = (offset + i) % BLOCK_SIZE; return the_data[block_index][data_index]; } What is the value of myDeque[13]? What is the value of myDeque.back()? What is the value of myDeque.front()?

More Related