!!!Chapter 9 Sequential Containers (9.4 ~ 9.7)

9.4 How a vector Grows

To support fast random access, vector elements are stored contiguously - each element is adjacent to the previous element. (so that index can work)

When there is no space for a new element, vector must allocate new memory to hold old elements plus the new one, copy the elements and deallocate the old memory.

For most applications, the best container to use is vector.

The way vectors achieve fast allocation is by allocating capacity beyond what is immediately needed.

9.4.1 capacity and reserve Members

The vector class includes two members, capacity and reserve, that let us interact with the memory-allocation part of vector's implementation.

capacity tells use how many elements the container could hold before it must allocate more space.

reserve lets us tell the vector how many elements it should be prepared to hold.

size is the number of elements in the vector; capacity is how many it could hold before new space must be allocated.capacity >= size.

vector<int> ivec;
cout << ivec.size() << ivec.capacity() <<endl;      //size is 0, capacity is 0

for(vector<int>::size_type ix = 0; ix != 24; ++ix)
ivec.push_back(ix);
cout << ivec.size() << ivec.capacity() <<endl;      //size is 24, capacity is 32

ivec.reserve(50);
cout << ivec.size() << ivec.capacity() <<endl;      //size is 24, capacity is 50

//as long as there is excess capacity, vector must not reallocate
while (ivec.size()!= ivec.capacity())
ivec.push_back(0);
cout <<ivec.size() << ivec.capacity() <<endl;       //size is 50, capacity is 50

ivec.push_back(0);
cout <<ivec.size() << ivec.capacity()<<endl;        //size is 51, capacity is 100. 
//so the library will double capacity each time (VC gives different capacity value)

We can implement vector differently, but:

1. it must provide reserve and capacity functions.

2. it must not allocate new memory until it is forced to do so.

9.5 Deciding Which Container to Use

whether elements are stored contiguously has significant impacts:

1. The costs to add or delete elements from the middle of the container

2. The costs to perform nonsequential access to elements of the container

vector and deque provide fast nonsequential access to elements at the cost of making it expensive to add or remove elements anywhere other than the ends of the container.

list supports fast insertion and deletion anywhere but at the cost of making nonsequential access to elements expensive.

How Insertion Affects Choice of Container

list: inserting or removing an element in a list does not move any other elements. But random access is not supported

vector: inserting or removing anywhere except at the back of a vector requires that each element to the right of the inserted(or deleted) element to be moved.

deque:

1. like vector, it is inefficient to insert or erase elements in the middle of the deque

2. unlike vector, a deque offers efficient insert and erase at the front as well as the back.

3. unlike list and like vector, deque supports fast random access to any element

4. Inserting elements at the front or back of a deque does not invalidate any iterators. Erasing the front/back element invalidates only iterators referring to the elements erased. Inserting or erasing anywhere else invalidates all iterators. ??? implementation?

Hints on Selecting Which Container to Use

1. If the program requires random access to elements, use a vector or a deque

2. If the program needs to insert or delete elements in the middle of the container, use a list

3. If the program needs to insert or delete elements at the front and the back, but not in the middle, of the container, use a deque.

4. If we need to insert elements in the middle of the container only while reading input and then need random access to the elements, consider reading them into a list and then reordering the list as appropriate for subsequent access and copying the reordered list into a vector.

When you are not certain which container to use. Try uses only operations common to both vector and lists: Use iterators, not subscripts, and avoid random access to elements.

9.6 strings Revisited P 337

string supports most of the sequential container operations. String support the same operations that vector support: The exceptions are:

1. string does not support stack operation: front, back, pop_back.

2. string does not support constructor that takes a single size parameter.

String-only functions:

1. substr operation

2. append/replace functions

3. search operations

4. compare operations

9.7 Container Adaptors

An adaptor is a mechanism for making one thing act like another.

A container adaptor takes an existing container type and makes it act like a different abstract type.

To use an adaptor, we must include its associated header:

#include <stack>    //stack adaptor
#include <queue>    //both queue and priority_queue adaptors

Initializing an Adaptor
Each adaptor defines two constructors:

1. The default constructor that creates an empty object

2. A constructor that takes a container and makes a copy of that container as its underlying value.

stack<int> stk;         //empty object
stack<int> stk2(deq);   //deq is a deque<int>

Overriding the Underlying Container Type

By default both stack and queue are implemented in terms of deque, and priority_queue is implemented on a vector.

We can override the default container type by naming a sequential container as a second type argument when creating the adaptor:

//empty stack implemented on top of vector
stack<string, vector<string> > str_stk;
//str_stk2 is implemented on top of vector and holds a copy of svec
stack<string, vector<string> > str_stk2(svec);

There are constraints on which containers can be used for a given adaptor:

1. any sequential container can be used for a stack

2. queue adaptor required push_front, so could be built on a deque/list but not a vector.

3. priority_queue requires random access, so could be build on a deque/vector but not list.

Common Adaptor Operations and Types
size_typeType large enough to hold size of largest object of this type
value_typeElement type
container_typeType of the underlying container on which the adaptor is implemented
A a;Create a new empty adaptor named a
A a(c);Create a new adaptor named a with a copy of the container c.
Relational OperatorsEach adaptor supports all relational operators: ==, !=, < <=, >, >=

9.7.1 Stack Adaptor

Stack Container Adaptor Operations
s.empty()return true if stack is empty
s.size()return number of elements in stack
s.pop()Removes, but does not return, the top element
s.top()Returns, but does not remove, the top element
s.push(item)Places a new top element

9.7.2 Queue and Priority Queue

queue uses a first-in, first-out storage and retrieval policy.

priority queue place a newly entered item ahead of all those with a lower priority. By default, the library uses the < operator on the element type to determine relative priorities.

Queue/ Priority Queue Operations
q.empty()return true if queue is empty
q.size()return number of elements in queue
q.pop()removes, but does not return the front element from the queue
q.front()returns, but does not remove, the front element on the queue
only for queue
q.back()returns, but does not remove, the back element on the queue
only for queue
q.top()returns, but does not remove the highest-priority element.
only for priority_queue
q.push(item)places a new element at the end of the queue
place a new element at its appropriate position based on priority in a priority queue

example:

#include<iostream>
#include<queue>
#include<string>          //must include the string header
using namespace std;
int main()
{
	priority_queue<string> pq;
	pq.push("abc");
	pq.push("bac");
	pq.push("cba");
	while(!pq.empty())
	{
		cout << pq.top() <<endl;
		pq.pop();
	}
}
out put is: cba, bac, abc 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值