从数组到向量
数组A[]中的元素与[0, n)内的编号是一一对应的。
每个元素均由(非负)编号唯一指代,并可直接访问。
A[ i ]的物理地址 = A + i*s , s为单个元素所占用的空间量。
因此也被称为线性数组(linear array)。
向量是数组的抽象与泛化,由一组元素按线性次序封装而成。
各元素与[0, n)中的秩(rank)一一对应。
元素的类型不限于基本类型
操作、管理维护更加简化、统一与安全。
最基础最简单最实用的东西放前面
insert(a,b) 在秩为a的位置插入b元素。
get(a) 返回秩为a的元素值。
put(a,b) 将当前rank为a的位置上的元素修改为b。
**remove(a)**将rank为a的元素剔除掉,并返回该元素值。
size() 返回元素个数。
disordered() 返回逆序对的个数 如果返回0表明从小到大排列。
find(x) 返回值为x的元素的秩,如果不存在则返回-1。
sort() 可以对向量排序(默认从小到大顺序排序)
search(x) 对于有序向量,用它来查找数值为x的元素,返回rank。如果没有找到则返回不超过x的最大的那个元素的rank。如果查找的全局都没有,而且比向量中最小的元素还要小的x,则返回-1 。这里的-1是我们假想的存在于向量所有元素前面的“一个哨兵”的秩,它的值是负无穷。如果查找的值有多个rank与之对应,则返回最后面的那个元素的秩(也就是相对最大的那个rank)。
uniquify() 对于一个有序的向量,我们在其中把所有的重复的元素都剔除掉,只保留一个拷贝。
Vector模板类
封装!
看一下大概的摸样,体会封装的妙处!
typedef int Rank; //秩
#define DEFAULT_CAPACITY 3 //默认初始容量(实际应用中可设置为更大)
template <typedef T> class Vector{ //向量模板类
private: Rank _size; int _capacity; T* _elem; //规模、容量、数据区
protected:
/*...内部函数*/
public:
/*...构造函数*/
/*...析构函数*/
/*...只读接口*/
/*...可写接口*/
/*...遍历接口*/
};
构造与析构
构造方法:
Vector(int c = DEFAULT_CAPACITY){ //默认
_elem = new T[_capacity = c];
_size = 0;
}
Vector(T const * A, Rank lo, Rank hi){ //数组区间复制
copyFrom(A, lo, hi);
}
Vector(Vector<T> const& V, Rank lo, Rank hi){ //向量区间复制
copyFrom(V._elem, lo, hi);
}
Vector(Vector<T> const& V){ //向量整体复制1
copyFrom(V._elem, 0, V._size);
}
析构方法:
~Vector(){ //释放内部空间
delete [] _elem;
}
复制
说在前面:当我们描述一个区间的时候往往是左闭右开的形式。
template <typedef T>
void Vector<T>::copyFrom(T* const A, Rank lo, Rank hi){
_elem = new T[_capacity = 2*(hi - lo)]; //分配空间
_size = 0; //规模清零
while(lo < hi) //A[lo, hi)内的元素逐一复制到_elem[0, hi-lo)
_elem[_size++] = A[lo++];
}
其中给capacity开2倍的需要的空间,主要目的在于:这样预留了一些空间之后就可以使得我们在接下来足够长的时间之内不会因为有必要扩容,而打断我们的计算过程。
关于可扩充向量与无序向量
:
请点击链接:可扩充向量与无序向量
无序是元素间可比是否相等;而有序是指元素可比大小。
关于有序向量
有序向量
有序序列中,任意一对相邻元素顺序。
无序序列中,总有一对相邻元素逆序。
有序向量请点击链接:有序向量详解
只要向量本身支持大小比较,我们就可以把无需向量转换为有序向量。