Data Structures with C++ Using STL Chapter 4向量容器---笔记

4.1

STL容器类的3个种类:顺序容器、适配器容器、关联容器。顺序容器按照线性次序位置存储数据,关联容器按照存储元素,如名字、社会保险编号,程序通过键访问关联容器中的元素,这些键可能与元素在容器中的位置无关。适配器包含另一个容器作为其基本存储结构,然而,适配器向程序员提供的接口仅仅是底层存储结构操作的一个受限子集。

4.2

模板类

template <typename T>
class templateClass
{
    public:
        templateClass(const T& item);
        //构造函数,带有类型T参数
        T f();
        //成员函数返回一个类型T数值
        void q(const T& item)
        //成员函数有一个类型T参数
    private:
        T dataValue;
    ...
};

通常,模板类中函数的参数通过常量引用传递。

为了把函数与类联系起来,函数头文件把类作用域运算符表达式store<T>::与函数名放在一起

template <typename T>
store<T>::store (const T& item):value(item)
{}

为了声明类型是模板类的对象,编译器需要根据特定的模板参数,创建一个具体的类型,为了做到这样,把类型放在类名后的尖括号中

templateClass<type> object(argument list);
store<int> intStore(5);  //数据值为整形类型

4.3

向量是基于模板的类,它存储相同数据类型的元素。与数组一样的是,向量对象允许通过下标运算符直接访问元素。然而,与数组不同的是,向量保留其大小信息,且提供相关的size()函数,程序员利用此函数可以访问向量的元素个数

//声明向量,长度为5,包含整型数值0
vector<int> intVector(5);

向量也可以类似于数组声明

向量声明不能使用大括号中的初始化表,只能先声明数组,然后把数组地址范围作为参数传递给构造函数

int intArray[5] = {9,2,7,3,12};
vetor<int> intVetor(intArray,intArray+5);

函数push_back()取类型T的元素,并将这个元素添加到向量的尾部,向量大小自动加1。向量类提供函数back()来访问和更新尾部元素,对于非常量向量,此函数可以用在赋值语句的任何一边,对于常量向量,back()提供了向量中的最后元素数值的只读访问。

cout << v.back();       //输出:'u'
v.push_back('w');       //在向量末尾添加'x'
v.back() = 'y';             //把尾部的'w'变为'y'

函数pop_back()删除向量中的最后元素,其下标为size()-1,并把向量的大小减1。程序员可以通过调用empty()检测向量是否为空,函数empty()在size() == 0时返回布尔值true。

函数resize()使用参数n改变向量的大小。此函数允许有另一个指明填充值的第二个参数,默认情况下,填充值为T(),如果新的大小大于当前大小,则向量通过添加n-size()个新元素来增长。现有的所有元素保持不变,把填充值赋给新元素。如果新的大小小于当前大小,resize()操作通过“砍掉”向量尾部的元素来收缩向量,前n个元素保持不变,向量丢掉其余的size()-n个元素。

int arr[] = {7,4,9,3,1};
int arrSize = sizeof(arr)/sizeof(int);
vector<int> v(arr,arr+arrSize);
v.resize(2*arrSize);      //向量大小加倍,填充值为0
v.resize(4);                     //向量收缩,数据丢失
v.resize(10,1);               //向量增长到大小为10,并填充1
//向量API
vetor();
 //创建一个空向量,这是默认的构造函数。
vetor(int n,const T&value = T());
 //创建具有n个元素的向量,每个元素具有指定的数值,如果忽略value参数,则元素用类型T的默认值填充,类型T必须有默认的构造函数,类型T的默认值由T()指定
vetor(T *first,T *last);
 //用地址范围(first,last)初始化向量,符号*first和*last是指针表示方法
T&back();
 //返回向量尾部数据项的数值,前提条件:向量必须至少包含一个元素
const T&back() const;
 //back()的常量版本
bool empty() const;
 //如果向量为空,则返回true否则返回false
T& operator[](int i);
 //可以取得或修改下标为i的向量元素,后置条件:如果运算符出现在赋值语句的左边,则右边的表达式改变下标引用的元素
const T& operator[](int i) const;
 //下标运算符的常量版本
void push_back(const T&value);
 //在向量的尾部增加一个数值,后置条件:向量的尾部有一个新元素,并且向量的大小增加1
void pop_back();
 //删除向量尾部的数据项,前提条件:向量非空,后置条件:向量尾部有一个新的元素,或者向量为空,向量的大小减1
void resize(int n,const T& fill = T());
 //改变向量的大小,后置条件:向量大小为n
int size() const;
 //返回向量中元素的数目

当对象为常量时,程序员只能调用类中用const修饰符声明的成员函数。

4.4

insertionSort()函数假定第一个元素处于正确的位置,因此,此函数需要在1到v.size()~1范围内进行n-1遍来排序其余的元素。对于一个一般的i,在进行第i遍时,0~i-1范围内的元素已经排序完毕,而第i遍的任务则是通过扫描以前已分类的子表,给v[i]在0~i的子表范围内找到正确的位置。复制v[i]到一个称作target的临时对象中。向下扫描表,把target与v[i-1],v[i-2]等依次比较。这个过程在小于或等于target的第1个元素v[j]处停止,或者直到表的开始处(j=0)停止。当v[i]小于以前任何一个排序过的元素时,后一种条件成立,这样,v[i]将占有新的排序后子表的第1个位置。在扫描过程中,把每个大于target(原来的v[i])到那个位置。与选择排序不同的是,插入排序只是把数据移到右边,不执行交换。

template <typename T>
void insertionSort(vector<T>& v)
{
    int i,j,n = v.size();
    T target;
    //将v[i]放到子表v[0] ... v[i-1],1 <= i < n中
    //使之处于正确的位置
    for(i = 1; i<n ; i++)
    {
        //下标j从v[i]向下扫描表,查找放置target的正确位置,将它赋值给v[j]
        j = i;
        target = v[i];
        //只要target  < v[j-1],并且没有遇到表的开始,就通过向下扫描定位插入点
        while(j > 0 && target < v[j-1])
        {
            //将元素在表中向上移动,留出插入的空间
            v[j] = v[j-1];
            j--;
        }
        //找到位置,插入目标
        v[j] = target;
    }
}
posted @ 2012-11-27 14:07  茉莉花茶  阅读(1059)  评论(0)    收藏  举报