1. 数组
对于数组 A = { a 0 , a 1 , . . . , a n − 1 } A = {\{a_0,a_1,...,a_{n-1}\}} A={a0,a1,...,an−1},任何 0 ≤ i < j < n 0 \le i < j < n 0≤i<j<n,A[i]都是A[j]的前驱(predecessor),A[j]都是A[i]的后继(successor)。任一元素的所有前驱构成其前缀(prefix),所有后继构成其后缀(suffix)。
2. 向量
向量各元素的秩(rank)互异,且均为[0,n)内的整数。具体地,若元素e的前驱元素共计r个,则其秩就是r。
3. 动态空间管理
向量实际规模与其内部数组容量的比值(size/capacity),称作装填因子(load factor)。
3.1 可扩充向量(extendable vector)
ß另行申请一个容量更大的数组,将原数组中的成员集体搬迁至新的空间,原数组所占的空间及时释放。
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;
}
4. 无序查找
4.1 顺序查找(sequential search)
template <typename T>
Rank Vector<T>::find(T const& e, Rank lo, Rank hi) const{
while((lo < hi--) && (e != _elem[hi]));
return hi;
}
- 查找秩最大的元素,故采用自后向前的查找顺序。
- 查找失败时统一返回-1.
- while控制的循环体现了C/C++逻辑表达式的短路求值(short-circuit evaluation)特性。
- 逻辑与和逻辑或操作符总是先计算其左操作数,然后再计算其右操作数。只有在仅靠左操作数的值无法确定该逻辑表达式的结果时,才会求解其右操作数。
4.2 唯一化
无序向量
自前向后注意考查各元素,在其前缀中寻找与其相同者。O(n2)
template <typename T> int Vector<T>::deduplicate(){
int oldSize = _size;
Rank i = 1;
while(i < _size){
(find(_elem[i], 0, i) < 0)? // 在其前缀中寻找相同者
i++ : remove(i);
}
return oldSize - _size;
}
有序向量
O(n)
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;
}