2.1 Vector(向量)

2.1.1 向量 ADT接口

作为一种抽象的向量类型,向量对象应支持如下操作接口

操作接口功能适用对象
size()报告向量当前的规模向量
get(r )获取秩为r的元素向量
put(r,e)用e替换秩为r 的元素数值向量
insert(r,e)e作为秩为r的元素插入,原后继元素依次后移向量
remove(r )删除秩为r的元素,返回该元素中原存放的对象向量
disordered()判断所有元素是否已按非降序排列向量
sort()调整各元素的位置,使之按非降序排列向量
find(e)查找等于e且秩最大的元素向量
search(e )查找目标元素e,返回不大于e且秩最大的元素有序向量
deduplicate()剔除重复元素向量
uniquify()剔除重复元素有序向量
traverse()遍历向量并统一处理所有元素,处理方法由函数对象指定向量
2.1.2 Vector(向量)-模板类
typedef int Rank;//秩
#define DEFAULT_CAPACITY 3//默认的初始容量(实际应用中可以设置为更大)
template <typename T> class Vector{//向量模板类
protected:
    Rank _size; int _capacity; T *_elem;//规模,容量,数据区
    void copyFrom(T const *A,Rank lo ,Rank hi);//复制数组区间A[lo,ho)
    void expand();//空间不足时扩容
    void shrink();//装填因子过小时压缩
    bool bubble(Rank lo,Rank hi);//扫描交换
    void bubbleSort(Rank lo,Rank hi);//起泡排序算法
    Rank max(Rank lo,Rank hi);//选取最大元素
    void selectionSort(Rank lo,Rank hi);//选择排序算法
    void merge(Rank lo,Rank mi,Rank hi);//归并算法
    void mergeSort(Rank lo,Rank hi);//归并排序算法
    Rank partition(Rank lo,Rank hi);//轴点构建算法
    void quickSort(Rank lo,Rank li);//快速排序算法
    void heapSort(Rank lo,Rank hi);//堆排序
public:
//构造函数
    Vector(int c=DEFAULT_CAPACITY,int s=0,T v=0)//容量为c,规模为S,所有元素初始为V
    {_elem=new T[_capacity=c];for(_size=0;_size<s;_elem[_size++]=v);}
    Vector(T const * A,Rank n){copyFrom(A,0,n);}//数组整体复制
    Vector(T const *A,Rank lo,Rank hi){copyFrom(A,lo,hi);}//区间
    Vector(Vector<T> const& V){copyFrom(V._elem,0,V._size);}//向量整体复制
    Vector(Vector<T> const&V,Rank lo,Rank hi){copyFrom(V._elem,lo,hi);}//区间
//析构函数
    ~Vector(){delete[] _elem;}//释放内部空间
//只读访问接口
    Rank size() const{return _size;}//规模
    bool empty() const{return !_size;}//判空
    int disordered()const;//判断向量是否已排序
    Rank find(T const& e)const{return find(e,0,_size);}//无序向量整体查找
    Rank find(T const&e,Rank lo,Rank hi)const;//无序向量区间查找
    Rank search(T const&e)//有序向量整体查找
    {return(0>=_size)?-1:search(e,0,_size);}
    Rank search(T const&e,Rank lo,Rank hi) const;//有序向量区间查找
//可写访问接口
    T& operator[](Rank r)const;//重载下标操作符,可以类似数组形式引用各元素
    Vector<T>& operator =(Vector<T>const&);//重载赋值操作符
    T remove(Rank r);//删除秩为r的元素
    int remove(Rank lo,Rank hi);//删除秩区间[lo,hi)之内的元素
    Rank insert(Rank r,T const&e);//插入元素
    Rank insert(T const&e){return insert(_size,e);}//默认作为末元素插入
    void sort(Rank lo,Rank hi);//对[lo,hi)排序
    void sort(){return sort(0,_size);}//对整体元素排序
    void unsort(Rank lo,Rank hi);//对[lo,hi)置乱
    void unsort(){unsort(0,_size);}//整体置乱
    int deduplicate();//无序去重
    int uniquify();//有序去重
//遍历
    void traverse(void (*)(T&));//遍历(使用函数指针,只读或者局部性修改)
    template <typename VST> void traverse(VST&);//遍历(使用函数对象,可全局性修改)
};//Vector
2.1.3 构造和析构函数
2.1.3.1 默认构造方法
    Vector(int c=DEFAULT_CAPACITY,int s=0,T v=0)//容量为c,规模为S,所有元素初始为V
    {_elem=new T[_capacity=c];for(_size=0;_size<s;_elem[_size++]=v);}
2.1.3.2 基于复制的构造方法
template <typename T>//元素类型
void Vector<T>::copyFrom(T const* A,Rank lo,Rank hi){//以数组区间A[lo,hi)为蓝本复制对象
    _elem=new T[_capacity=2*(hi-lo)];_size=0;//分配空间,规模清零
    while(lo<hi){//A[lo,hi)内的元素逐一
        _elem[_size++]=A[lo++];//复制至_elem[0,hi-lo];
    }
}
2.1.3.3赋值操作符重载
template <typename T> Vector<T>&Vector<T>::operator=(Vector<T>const& V){//重载
    if(_elem) delete[] _elem;//释放原有的内容
    copyFrom(V._elem,0,V.size());//整体复制
    return *this;//返回当前对象的引用
 }
2.1.3.4析构函数

析构函数与构造函数不同,同一对象只有只能有一个析构函数,不得重载

 ~Vector(){delete[] _elem;}//释放内部空间
2.1.4动态空间管理

装填因子: 向量实际规模与其内部数组容量的比值(即 _size/_capacity),亦称作装填因子

目的:保证向量的装填因子既不致于超过1,也不至于太接近0

2.1.4.1 扩容
template <typename T> void Vector<T>::expand(){//向量空间不足时扩容
    if(_size<_capacity) return;//尚未满员时不必扩容
    if(_capacity<DEFAULT_CAPACITY) _capacity=DEFAULT_CAPACITY;//不低于最小容量
    T* oldElem=_elem; _elem=new T[_capacity<<=1];//容量加倍
    for(int i=0;i<_size;i++)
        _elem[i]=oldElem[i];//复制原向量的内容
    delete[]oldElem;//释放原空间
}
2.1.4.2 缩容
template <typename T>void Vector<T>::shrink(){//装填因子过小时压缩向量所占空间
    if(_capacity<DEFAULT_CAPACITY) return;//不致压缩到DEFAULE_CAPACITY以下
    if(_size<<2>_capacity) return;//以25%为界,
    T *oldElem=_elem;_elem=new T[_capacity>>=1];//容量减半
    for(int i=0;i<_size;i++) _elem[i]=oldElem[i];//复制原向量的内容
    delete []oldElem;//释放原空间
}
2.1.5 常规向量
2.1.5.1 重载操作符[] 直接引用元素
template <typename T> T& Vector<T>::operator[](Rank r)const//重载下标操作符号
{  return _elem[r];}
2.1.5.2 置乱器
template <typename T>void Vector<T>::unsort(Rank lo,Rank hi){//等概率随机置乱区间[lo,hi)
    T *V=_elem+lo;//将子向量_elem[lo,hi)视作另一向量V[0,hi-lo)
    for(Rank i=hi-lo;i>0;i--){//自后向前
        swap(V[i-1],V[rand()%i]);//将V[i-1]与V[0,i)中某一元素随机交换
    }
}
2.1.5.4 比较器

注意:这里使用的==和<符号都是重载过的

当然:也可以将对比操作和和比较操作分别封装成通用的判等器和比较器。这里主要用的重载后的操作符比较

template <typename T> static bool lt(T*a,T*b){return lt(*a,*b);}//less than
template <typename T> static bool lt(T&a,T&b){return a<b;}//less than
template <typename T> static bool eq(T*a,T*b){return eq(*a,*b);}//equal
template <typename T> static bool eq(T&a,T&b){return a==b;}//equal
2.1.5.4 顺序查找
template <typename T>//无序向量的顺序查找:返回最后一个元素e的位置;失败时,返回lo-1
Rank Vector<T>::find(T const&e,Rank lo, Rank hi)const{//assert: 0<=lo<hi<=_size
    while((lo<hi--)&&(e!= _elem[hi]));//从后往前,顺序查找
    return hi;//若hi<lo,则意味失败否则即命中元素的秩
}
2.1.5.5 插入
template <typename T> Rank Vector<T>::insert( Rank r, T const & e ) { //0<=r<=size
 expand(); //若有必要,扩容
 for ( int i = _size; i > r; i-- ) //O(n-r):自后向前
 _elem[i] = _elem[i - 1]; //后继元素顺次后移一个单元
 _elem[r] = e; _size++; return r; //置入新元素,更新容量,返回秩
}
2.1.5.6删除
区间删除
template <typename T> int Vector<T>::remove(Rank lo,Rank hi){//删除区间[li,hi)
    if(lo==hi){return 0;}//出于效率考虑,单独处理退化情况
    while(hi<_size) _elem[lo++]=_elem[hi++];//[hi,_size)顺次前移hi-lo个单元
    _size=lo;//更新规模,直接丢弃尾部[lo,_size=hi)区间
    shrink();//若有必要则缩容
    return hi-lo;//返回被删除元素的数目
}
单元素删除
template <typename T> T Vector<T>::remove(Rank r){//删除向量中秩为r的元素,0<=r<size
    T e=_elem[r];//备份被删除元素
    remove(r,r+1);//调用区间删除算法,等效对区间[r,r+1)的删除
    return e;//返回被删除的元素
}
2.1.5.7 唯一化
template <typename T> int Vector<T>::deduplicate(){//删除无序向量中的重复元素(高效版)
    int oldSize=_size;//记录原规模
    Rank i=1;//从_elem[1]开始
    while(i<_size)//自前向后逐一考察各元素_elem[i]
        (find(_elem[i],0,i))?//在其前缀中寻找与之雷同者(至多一个)
        i++:remove(i);//若无雷同则考察其后继,否则删除雷同者
    return oldSize-_size;//向量规模变化量,即被删除的元素
}
2.1.5.8 遍历-向量的遍历操作接口
template <typename T> void Vector<T>::traverse(void (*visit)(T&))//借助函数指针机制
{
       for(int i=0;i<_size;i++) visit(_elem[i]);//遍历向量
}
template <typename T> template <typename VST>//元素类型,操作器
void Vector<T>::traverse(VST &visit)//借助函数对象机制
{
     for(int i=0;i<_size;i++) visit(_elem[i]);
}
2.1.5.9实例-基于遍历接口,实现向量中所有元素加1
template <typename T> struct Increase//函数对象:递增一个T类对象
{
    virtual void operator() (T&e){e++;}
};
template <typename T> void increase(Vector<T>&V){
    V.traverse(Increase<T>());}//以Increase<T>() 为基本操作对象
2.1.6 有序向量
2.1.6.1比较器
template <typename T> static bool lt(T*a,T*b){return lt(*a,*b);}//less than
template <typename T> static bool lt(T&a,T&b){return a<b;}//less than
template <typename T> static bool eq(T*a,T*b){return eq(*a,*b);}//equal
template <typename T> static bool eq(T&a,T&b){return a==b;}//equal
2.1.6.2有序性甄别
template <typename T> int Vector<T>::disordered() const{//返回向量中逆序相邻元素对的总数
    int n=0;//计数器
    for(int i=1;i<_size;i++)
        if(_elem[i-1]>_elem[i]) n++;//逆序则计数
    return n;//向量有序当且仅当n=0
}
2.1.6.3有序向量唯一化
template <typename T> int Vector<T>::uniquify(){//有序向量重读元素剔除算法(高效版)
    Rank i=0,j=0;//各对互异“相邻”元素的秩
    while(++j<_size)//逐一扫描,直至末元素
        if(_elem[i]!=_elem[j])//跳过雷同者
        _elem[++i]=_elem[j];//发现不同元素时,向前移至紧邻于前者右侧
    _size=++i;shrink();//直接截除尾部多余元素
    return j-i;//向量规模变化量,即被删除的元素的总数
}
2.1.6.4有序向量中的元素查找
Rank Vector<T>::search(T const&e,Rank lo,Rank hi)const//assert: 0<=lo<hi<=_size
{
    return (rand()%2)?//按50%的概率随机使用二分查找和Fibonacci查找
    binSearch(_elem,e,lo,hi):fibSearch(_elem,e,lo,hi);
}
二分查找

版本A-常数较大为1.5

//二分查找算法: 在有序区间[lo,hi)内查找元素e,0<=lo<=hi<=_size
template <typename T> static Rank binSearch(T *A,T const&e,Rank lo,Rank hi)
{
    while(lo<hi){//每次迭代可能作两次比较判断有三个分支
        Rank mi=(lo+hi)>>1;//以中点作为轴点
        if(e<A[mi]) hi=mi;//深入前半段[li,hi)
        else if(A[mi]<e) lo=mi+1;//深入后半段(mi,hi)继续查找
        else return mi;//在mi处命中
    }//成功查找可终止
    return -1;//查找失败
}//有多个命中元素时,不能保证返回秩元素最大者;查找失败时简单的返回-1,而不能指示失败的位置

版本B-常数较小

//二分查找算法: 在有序区间[lo,hi)内查找元素e,0<=lo<=hi<=_size
template <typename T> static Rank binSearch(T *A,T const&e,Rank lo,Rank hi)
{
    while(1<hi-lo){//每步迭代仅需做一次比较判断,有两个分支: 成功查找不能提前终止
        Rank mi=(lo+hi)>>1;//以中点为轴点
        (e<A[mi])?hi=mi:lo=mi;//经比较后确定深入[lo,hi)或(mi,hi)
    }//出口时hi=lo+1,查找时区间仅含一个元素A[lo]
    return (e==A[lo])?lo:-1;//查找成功时返回对应的秩;否则统一返回-1
}//有多个命中元素时,不能保证返回秩元素最大者;查找失败时简单的返回-1,而不能指示失败的位置

版本C-提供信息多

//二分查找算法: 在有序区间[lo,hi)内查找元素e,0<=lo<=hi<=_size
template <typename T> static Rank binSearch(T *A,T const&e,Rank lo,Rank hi)
{
    while(lo<hi){//每步迭代仅需做一次比较判断,有两个分支: 成功查找不能提前终止
        Rank mi=(lo+hi)>>1;//以中点为轴点
        (e<A[mi])?hi=mi:lo=mi+1;//经比较后确定深入[lo,hi)或(mi,hi)
    }//成功查到不能提前终止
    return --lo;//循环结束时,为大于e的元素的最小秩,故lo-1即不大于e的元素的最大秩
}//有多个命中元素时,总保证返回秩元素最大者;查找失败时能够返回失败的位置
Fibnoacci查找

Fibonacci数列类

class Fib{
    private:
    int f, g;//f=fib(k-1),g=fib(k)均为int型,很快就会数值溢出
    public: 
    Fib(int n){//初始化不小于n的最小Fibonacci项
        f=1;g=0;
        while(g<n) next();
    }
    int get(){return g;}
    int next(){g+=f;f=g-f;return g;}
    int prev(){f=g-f;g-=f;return g;}
};

版本A

class Fib{
    private:
    int f, g;//f=fib(k-1),g=fib(k)均为int型,很快就会数值溢出
    public:
    Fib(int n){//初始化不小于n的最小Fibonacci项
        f=1;g=0;
        while(g<n) next();
    }
    int get(){return g;}
    int next(){g+=f;f=g-f;return g;}
    int prev(){f=g-f;g-=f;return g;}
};
//在有序向量区间[lo,hi)内查找元素e,0<=lo<=hi<=_size
template <typename T> static Rank fibSearch(T* A,T const&e,Rank lo,Rank hi){
    Fib fib(hi-lo);//用o(log_phi(n=hi-lo)时间创建fib数列
    while(lo<hi){//每步迭代可能要作两次比较判断,有三个分支
       while(hi-lo<fib.get()) fib.prev();//通过向前顺序查找(分摊O(1))-至多迭代几次
       Rank mi=lo+fib.get()-1;//确定Fib(k)-1的轴点
       if (e<A[mi]) hi=mi;//深入前半段[lo,mi)继续查找
       else if(A[mi]<e)lo=mi+1;//深入后半段(mi,hi)继续查找
       else     return mi;//在mi处命中
    }//成功查找可提前终止
    return -1;//查找失败
}//有多个命中元素时,不能保证返回秩的最大值;失败时简单的返回-1,而不能指示失败的位置
2.1.7 排序与下界

下界

任意问题在最坏的情况下的最低计算成本,称为复杂度下界

比较树

用节点表示算法过程中的不同状态,用有方向的边表示不同状态之间的相互转换,就可以将将算法转换为树形结构

估计下界

用比较树估计复杂度

2.1.8 排序器
2.1.7.1排序
template <typename T> void Vector<T>::sort(Rank lo,Rank hi){//向量区间[lo,hi)排序
    switch(rand()%5){//随机选取排序算法,可根据具体的问题的特点灵活选取或者扩容量
    case 0: bubbleSort(lo,hi);break;//起泡排序
    case 1: selectionSort(lo,hi);break;//选择排序
    case 2: mergeSort(lo,hi);break;//归并排序
    case 3: heapSort(lo,hi);break;//堆排序
    case 4: quickSort(lo,hi);break;//快速排序
    }
}
2.1.7.1.1 起泡排序
template <typename T> //向量的起泡排序
void Vector<T>::bubbleSort(Rank lo,Rank hi)//assert: 0<=lo<=hi<<_size
{
    while(!bubble(lo,hi--));//逐趟做扫描交换,直至全序
}
template <typename T> bool Vector<T>::bubble(Rank lo,Rank hi)
{
    bool sorted=true;//整体有序的标志
    while(++lo<hi){//从左向右,逐一检查各对相邻元素
        if(_elem[lo-1]>_elem[lo]){//若逆序
            sorted=false;
            swap(_elem[lo-1],_elem[lo]);//通过交换使局部有序
        }
    }
    return sorted;
}
2.1.7.1.2 归并排序

向量归并排序

template <typename T>//向量归并排序
void Vector<T>::mergeSort(Rank lo,Rank hi){//0<=lo<hi<=_size
    if(hi-lo<2) return;//单区间自然有序
    int mi=(lo+hi)>>1;//中点为界
    mergeSort(lo,mi);mergeSort(mi,hi);//分别排序
    merge(lo,mi,hi);//归并
}

有序向量的归并

template <typename T> //有序向量的归并
void Vector<T>::merge(Rank lo,Rank mi,Rank hi){//各自有序的子向量[lo,mi),[mi,hi)
    T *A=_elem+lo;//合并后的向量A[0,hi-lo)=_elem[lo,hi)
    int lb=mi-lo;T* B =new T[lb];//前子向量B[0,lb)=_elem[lo,hi);
    for(Rank i=0;i<lb;B[i]=A[i++]);//复制前子向量
    int lc=hi-mi; T * C=_elem+mi;//后子向量C[0,lc)=_elem[mi,hi)
    for(Rank i=0,j=0,k=0;(j<lb)||(k<lc);){//B[j]和C[k]中的小者延续至A末尾
        if((j<lb)&&(!(k<lc)||(B[j]<=C[k]))) A[i++]=B[j++];
        if((k<lc)&&(!(j<lb)||(C[k]<B[j]))) A[i++]=C[k++];
    }
    delete[]B;//释放临时空间B
}//归并后得到完整的有序向量[lo,hi)

2.1.9 Vector.h

#pragma once
class Fib { //Fibonacci数列类
private:
	int f, g; //f = fib(k - 1), g = fib(k)。均为int型,很快就会数值溢出
public:
	Fib(int n) //初始化为不小于n的最小Fibonacci项
	{
		f = 1; g = 0; while (g < n) next();
	} //fib(-1), fib(0),O(log_phi(n))时间
	int get() { return g; } //获取当前Fibonacci项,O(1)时间
	int next() { g += f; f = g - f; return g; } //转至下一Fibonacci项,O(1)时间
	int prev() { f = g - f; g -= f; return g; } //转至上一Fibonacci项,O(1)时间
};

2.2.2 Fib查找

//在有序向量区间[lo,hi)内查找元素e,0<=lo<=hi<=_size
template <typename T> static Rank fibSearch(T* A,T const&e,Rank lo,Rank hi){
    Fib fib(hi-lo);//用o(log_phi(n=hi-lo)时间创建fib数列
    while(lo<hi){//每步迭代可能要作两次比较判断,有三个分支
       while(hi-lo<fib.get()) fib.prev();//通过向前顺序查找(分摊O(1))-至多迭代几次
       Rank mi=lo+fib.get()-1;//确定Fib(k)-1的轴点
       if (e<A[mi]) hi=mi;//深入前半段[lo,mi)继续查找
       else if(A[mi]<e)lo=mi+1;//深入后半段(mi,hi)继续查找
       else     return mi;//在mi处命中
    }//成功查找可提前终止
    return -1;//查找失败
}//有多个命中元素时,不能保证返回秩的最大值;失败时简单的返回-1,而不能指示失败的位置

向量Vector-模板完整代码

#include<iostream>
#include<cstdlib>
using namespace std;
typedef int Rank;//秩
#define DEFAULT_CAPACITY 3//默认的初始容量(实际应用中可以设置为更大)
template <typename T> class Vector{//向量模板类
protected:
    Rank _size; int _capacity; T *_elem;//规模,容量,数据区
    void copyFrom(T const *A,Rank lo ,Rank hi);//复制数组区间A[lo,ho)
    void expand();//空间不足时扩容
    void shrink();//装填因子过小时压缩
    bool bubble(Rank lo,Rank hi);//扫描交换
    void bubbleSort(Rank lo,Rank hi);//起泡排序算法
    Rank max(Rank lo,Rank hi);//选取最大元素
    void selectionSort(Rank lo,Rank hi);//选择排序算法
    void merge(Rank lo,Rank mi,Rank hi);//归并算法
    void mergeSort(Rank lo,Rank hi);//归并排序算法
    Rank partition(Rank lo,Rank hi);//轴点构建算法
    void quickSort(Rank lo,Rank li);//快速排序算法
public:
    void heapSort(Rank lo,Rank hi);//堆排序
public:
//构造函数
    Vector(int c=DEFAULT_CAPACITY,int s=0,T v=0)//容量为c,规模为S,所有元素初始为V
    {_elem=new T[_capacity=c];for(_size=0;_size<s;_elem[_size++]=v);}
    Vector(T const * A,Rank n){copyFrom(A,0,n);}//数组整体复制
    Vector(T const *A,Rank lo,Rank hi){copyFrom(A,lo,hi);}//区间
    Vector(Vector<T> const& V){copyFrom(V._elem,0,V._size);}//向量整体复制
    Vector(Vector<T> const&V,Rank lo,Rank hi){copyFrom(V._elem,lo,hi);}//区间
//析构函数
    ~Vector(){delete[] _elem;}//释放内部空间
//只读访问接口
    Rank size() const{return _size;}//规模
    bool empty() const{return !_size;}//判空
    int disordered()const;//判断向量是否已排序
    Rank find(T const& e)const{return find(e,0,_size);}//无序向量整体查找
    Rank find(T const&e,Rank lo,Rank hi)const;//无序向量区间查找
    Rank search(T const&e)//有序向量整体查找
    {return(0>=_size)?-1:search(e,0,_size);}
    Rank search(T const&e,Rank lo,Rank hi) const;//有序向量区间查找
//可写访问接口
    T& operator[](Rank r)const;//重载下标操作符,可以类似数组形式引用各元素
    Vector<T>& operator =(Vector<T>const&);//重载赋值操作符
    T remove(Rank r);//删除秩为r的元素
    int remove(Rank lo,Rank hi);//删除秩区间[lo,hi)之内的元素
    Rank insert(Rank r,T const&e);//插入元素
    Rank insert(T const&e){return insert(_size,e);}//默认作为末元素插入
    void sort(Rank lo,Rank hi);//对[lo,hi)排序
    void sort(){return sort(0,_size);}//对整体元素排序
    void unsort(Rank lo,Rank hi);//对[lo,hi)置乱
    void unsort(){unsort(0,_size);}//整体置乱
    int deduplicate();//无序去重
    int uniquify();//有序去重
//遍历
    void traverse(void (*)(T&));//遍历(使用函数指针,只读或者局部性修改)
    template <typename VST> void traverse(VST&);//遍历(使用函数对象,可全局性修改)
};//Vector
template <typename T>//元素类型
void Vector<T>::copyFrom(T const* A,Rank lo,Rank hi){//以数组区间A[lo,hi)为蓝本复制对象
    _elem=new T[_capacity=2*(hi-lo)];_size=0;//分配空间,规模清零
    while(lo<hi){//A[lo,hi)内的元素逐一
        _elem[_size++]=A[lo++];//复制至_elem[0,hi-lo];
    }
}
template <typename T> Vector<T>&Vector<T>::operator=(Vector<T>const& V){//重载
    if(_elem) delete[] _elem;//释放原有的内容
    copyFrom(V._elem,0,V.size());//整体复制
    return *this;//返回当前对象的引用
 }
template <typename T> void Vector<T>::expand(){//向量空间不足时扩容
    if(_size<_capacity) return;//尚未满员时不必扩容
    if(_capacity<DEFAULT_CAPACITY) _capacity=DEFAULT_CAPACITY;//不低于最小容量
    T* oldElem=_elem; _elem=new T[_capacity<<=1];//容量加倍
    for(int i=0;i<_size;i++)
        _elem[i]=oldElem[i];//复制原向量的内容
    delete[]oldElem;//释放原空间
}
template <typename T>void Vector<T>::shrink(){//装填因子过小时压缩向量所占空间
    if(_capacity<DEFAULT_CAPACITY) return;//不致压缩到DEFAULE_CAPACITY以下
    if(_size<<2>_capacity) return;//以25%为界,
    T *oldElem=_elem;_elem=new T[_capacity>>=1];//容量减半
    for(int i=0;i<_size;i++) _elem[i]=oldElem[i];//复制原向量的内容
    delete []oldElem;//释放原空间
}
template <typename T> T& Vector<T>::operator[](Rank r)const//重载下标操作符号
{   return _elem[r];}
template <typename T>void Vector<T>::unsort(Rank lo,Rank hi){//等概率随机置乱区间[lo,hi)
    T *V=_elem+lo;//将子向量_elem[lo,hi)视作另一向量V[0,hi-lo)
    for(Rank i=hi-lo;i>0;i--){//自后向前
        swap(V[i-1],V[rand()%i]);//将V[i-1]与V[0,i)中某一元素随机交换
    }
}
template <typename T> static bool lt(T*a,T*b){return lt(*a,*b);}//less than
template <typename T> static bool lt(T&a,T&b){return a<b;}//less than
template <typename T> static bool eq(T*a,T*b){return eq(*a,*b);}//equal
template <typename T> static bool eq(T&a,T&b){return a==b;}//equal
template <typename T>//无序向量的顺序查找:返回最后一个元素e的位置;失败时,返回lo-1
Rank Vector<T>::find(T const&e,Rank lo, Rank hi)const{//assert: 0<=lo<hi<=_size
    while((lo<hi--)&&(e!= _elem[hi]));//从后往前,顺序查找
    return hi;//若hi<lo,则意味失败否则即命中元素的秩
}
template <typename T> Rank Vector<T>::insert( Rank r, T const & e ) { //插入元素
 expand(); //若有必要,扩容
 for ( int i = _size; i > r; i-- ) //O(n-r):自后向前
 _elem[i] = _elem[i - 1]; //后继元素顺次后移一个单元
 _elem[r] = e; _size++; return r; //置入新元素,更新容量,返回秩
}

template <typename T> int Vector<T>::remove(Rank lo,Rank hi){//删除区间[li,hi)
    if(lo==hi){return 0;}//出于效率考虑,单独处理退化情况
    while(hi<_size) _elem[lo++]=_elem[hi++];//[hi,_size)顺次前移hi-lo个单元
    _size=lo;//更新规模,直接丢弃尾部[lo,_size=hi)区间
    shrink();//若有必要则缩容
    return hi-lo;//返回被删除元素的数目
}
template <typename T> T Vector<T>::remove(Rank r){//删除向量中秩为r的元素,0<=r<size
    T e=_elem[r];//备份被删除元素
    remove(r,r+1);//调用区间删除算法,等效对区间[r,r+1)的删除
    return e;//返回被删除的元素
}
template <typename T> int Vector<T>::deduplicate(){//删除无序向量中的重复元素(高效版)
    int oldSize=_size;//记录原规模
    Rank i=1;//从_elem[1]开始
    while(i<_size)//自前向后逐一考察各元素_elem[i]
        (find(_elem[i],0,i))?//在其前缀中寻找与之雷同者(至多一个)
        i++:remove(i);//若无雷同则考察其后继,否则删除雷同者
    return oldSize-_size;//向量规模变化量,即被删除的元素
}
template <typename T> void Vector<T>::traverse(void (*visit)(T&))//借助函数指针机制
{
       for(int i=0;i<_size;i++) visit(_elem[i]);//遍历向量
}
template <typename T> template <typename VST>//元素类型,操作器
void Vector<T>::traverse(VST &visit)//借助函数对象机制
{
     for(int i=0;i<_size;i++) visit(_elem[i]);
}
template <typename T> struct Increase//函数对象:递增一个T类对象
{
    virtual void operator() (T&e){e++;}
};
template <typename T> void increase(Vector<T>&V)
{    V.traverse(Increase<T>());}//以Increase<T>() 为基本操作对象
template <typename T> int Vector<T>::disordered() const{//返回向量中逆序相邻元素对的总数
    int n=0;//计数器
    for(int i=1;i<_size;i++)
        if(_elem[i-1]>_elem[i]) n++;//逆序则计数
    return n;//向量有序当且仅当n=0
}
template <typename T> int Vector<T>::uniquify(){//有序向量重读元素剔除算法(高效版)
    Rank i=0,j=0;//各对互异“相邻”元素的秩
    while(++j<_size)//逐一扫描,直至末元素
        if(_elem[i]!=_elem[j])//跳过雷同者
        _elem[++i]=_elem[j];//发现不同元素时,向前移至紧邻于前者右侧
    _size=++i;shrink();//直接截除尾部多余元素
    return j-i;//向量规模变化量,即被删除的元素的总数
}

//二分查找算法: 在有序区间[lo,hi)内查找元素e,0<=lo<=hi<=_size
template <typename T> static Rank binSearch(T *A,T const&e,Rank lo,Rank hi)
{
    while(1<hi-lo){//每步迭代仅需做一次比较判断,有两个分支: 成功查找不能提前终止
        Rank mi=(lo+hi)>>1;//以中点为轴点
        (e<A[mi])?hi=mi:lo=mi+1;//经比较后确定深入[lo,hi)或(mi,hi)
    }//成功查到不能提前终止
    return --lo;//循环结束时,为大于e的元素的最小秩,故lo-1即不大于e的元素的最大秩
}//有多个命中元素时,总保证返回秩元素最大者;查找失败时能够返回失败的位置

class Fib{
    private:
    int f, g;//f=fib(k-1),g=fib(k)均为int型,很快就会数值溢出
    public:
    Fib(int n){//初始化不小于n的最小Fibonacci项
        f=1;g=0;
        while(g<n) next();
    }
    int get(){return g;}
    int next(){g+=f;f=g-f;return g;}
    int prev(){f=g-f;g-=f;return g;}
};
//在有序向量区间[lo,hi)内查找元素e,0<=lo<=hi<=_size
template <typename T> static Rank fibSearch(T* A,T const&e,Rank lo,Rank hi){
    Fib fib(hi-lo);//用o(log_phi(n=hi-lo)时间创建fib数列
    while(lo<hi){//每步迭代可能要作两次比较判断,有三个分支
       while(hi-lo<fib.get()) fib.prev();//通过向前顺序查找(分摊O(1))-至多迭代几次
       Rank mi=lo+fib.get()-1;//确定Fib(k)-1的轴点
       if (e<A[mi]) hi=mi;//深入前半段[lo,mi)继续查找
       else if(A[mi]<e)lo=mi+1;//深入后半段(mi,hi)继续查找
       else     return mi;//在mi处命中
    }//成功查找可提前终止
    return -1;//查找失败
}//有多个命中元素时,不能保证返回秩的最大值;失败时简单的返回-1,而不能指示失败的位置

template <typename T>//在有序向量区间[lo,hi)内,确定不大于e 的最后一个节点的秩
Rank Vector<T>::search(T const&e,Rank lo,Rank hi)const//assert: 0<=lo<hi<=_size
{
    return (rand()%2)?//按50%的概率随机使用二分查找和Fibonacci查找
    binSearch(_elem,e,lo,hi):fibSearch(_elem,e,lo,hi);
}

template <typename T> void Vector<T>::sort(Rank lo,Rank hi){//向量区间[lo,hi)排序
    switch(rand()%5){//随机选取排序算法,可根据具体的问题的特点灵活选取或者扩容量
    case 0: bubbleSort(lo,hi);break;//起泡排序
    case 1: selectionSort(lo,hi);break;//选择排序
    case 2: mergeSort(lo,hi);break;//归并排序
    case 3: heapSort(lo,hi);break;//堆排序
    case 4: quickSort(lo,hi);break;//快速排序
    }
}
template <typename T> //向量的起泡排序
void Vector<T>::bubbleSort(Rank lo,Rank hi)//assert: 0<=lo<=hi<<_size
{
    while(!bubble(lo,hi--));//逐趟做扫描交换,直至全序
}
template <typename T> bool Vector<T>::bubble(Rank lo,Rank hi)
{
    bool sorted=true;//整体有序的标志
    while(++lo<hi){//从左向右,逐一检查各对相邻元素
        if(_elem[lo-1]>_elem[lo]){//若逆序
            sorted=false;
            swap(_elem[lo-1],_elem[lo]);//通过交换使局部有序
        }
    }
    return sorted;
}
template <typename T>//向量归并排序
void Vector<T>::mergeSort(Rank lo,Rank hi){//0<=lo<hi<=_size
    if(hi-lo<2) return;//单区间自然有序
    int mi=(lo+hi)>>1;//中点为界
    mergeSort(lo,mi);mergeSort(mi,hi);//分别排序
    merge(lo,mi,hi);//归并
}
template <typename T> //有序向量的归并
void Vector<T>::merge(Rank lo,Rank mi,Rank hi){//各自有序的子向量[lo,mi),[mi,hi)
    T *A=_elem+lo;//合并后的向量A[0,hi-lo)=_elem[lo,hi)
    int lb=mi-lo;T* B =new T[lb];//前子向量B[0,lb)=_elem[lo,hi);
    for(Rank i=0;i<lb;B[i]=A[i++]);//复制前子向量
    int lc=hi-mi; T * C=_elem+mi;//后子向量C[0,lc)=_elem[mi,hi)
    for(Rank i=0,j=0,k=0;(j<lb)||(k<lc);){//B[j]和C[k]中的小者延续至A末尾
        if((j<lb)&&(!(k<lc)||(B[j]<=C[k]))) A[i++]=B[j++];
        if((k<lc)&&(!(j<lb)||(C[k]<B[j]))) A[i++]=C[k++];
    }
    delete[]B;//释放临时空间B
}//归并后得到完整的有序向量[lo,hi)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值