2.1.1 向量 ADT接口
作为一种抽象的向量类型,向量对象应支持如下操作接口
操作接口 | 功能 | 适用对象 |
---|---|---|
size() | 报告向量当前的规模 | 向量 |
get® | 获取秩为r的元素 | 向量 |
put(r,e) | 用e替换秩为r 的元素数值 | 向量 |
insert(r,e) | e作为秩为r的元素插入,原后继元素依次后移 | 向量 |
remove® | 删除秩为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(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的元素的最大秩
}//有多个命中元素时,总保证返回秩元素最大者;查找失败时能够返回失败的位置
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-模板完整代码
#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)