向量模板类

3.9插入

template<typename T>
Rank vector<T>::insert(T const & e, Rank r)
{
expand();//检查是否需要扩容。
for (Rank i = _size; i > r; i--)//自后向前,所有元素顺次后移一个单元
    _elem[i] = _elem[i - 1];
_elem[r] = e; _size++;
return r;
}

注意:元素搬迁的顺序不能颠倒,否则会因元素被覆盖而造成数据丢失。向量结构的插入较之列表结构,复杂度就集中在元素搬迁上,线性正比于后缀的长度。考虑最坏情况,依次从首部插入,元素移动个数成几何级数由N递减至1。故总体时间复杂度为O(N+N-1+N-2+….+1)=O(n^2)。

4.0删除

由于向量元素的特性,考察{1,2,3,4,5}一组向量。删除元素3,需要将4,5顺次前移一个单元{1,2,4,5,NULL},与插入元素同理,每次单个删除一个元素,需要时间线性正比其后继元素。若区间删除(2(rank),4(rank))变为{1,2,NULL,NULL,NULL}而所费时间与删除单个元素3完全相同。故应采用区间删除的办法来取代单个元素。

template<typename T>
int vector<T>::remove(Rank lo, Rank hi)
{//lo与hi必须合法[0,_size)
    if (lo == hi) return 0;
    while (hi < _size) {
        _elem[lo++] = _elem[hi++];
    }
    _size = lo;
    shrink();//装填因子25%为界,低于25%将缩容
    return hi-lo;
}

重载remove()接口以实现单元素删除。

template<typename T>
T vector<T>::remove(Rank r)
{   
    if(IsValid(r,0,_size)){
        T e = _elem[r];
        remove(r, r + 1);
        return e;
    }
    else return NULL;
}

4.1唯一化

对于无序向量来说,唯一化的办法只有遍历一遍向量O(n),剔除重复的,删除元素需要反复调用remove()接口。也需要O(n)时间。即总体时间复杂度为O(n^2)的时间。

template<typename T>
int vector<T>::deduplicate()
{
    Rank i = 1;
    int oldsize = _size;
    while (i < _size) {
        (find(_elem[i], 0, i) < 0) ? i++ : remove(i);//自前向后,与其所有前驱比较,找到一个删除一个。
    }
    return oldsize-_size;
}

针对有序向量,唯一化的工作即可在O(n)时间内完成。无序向量唯一化,时间复杂度主要集中在每次调用remove()接口上,每次只移动一个单元,如果能标记位置,一次前移多个单元,时间复杂度将大大下降。

以{1,3,5,5,5,5,5,5,6}为例。
采用deduplicate()接口,当指针处理到rank(3)时{1,3,5,5}find(_elem[3], 0,3)=2这时调用一次remove()接口,在接下来的4次比对中,需要连续调用4次remove()接口,这将大大提升复杂度。若能直接调用remove(2,7)即可在O(9+5)时间结束任务。
在处理当前问题是,发现重复元素必然是紧邻出现的。采取如下思路:

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;
}

i与j分别指向下一对相邻子区间的首元素每次将检查一对儿数据元素,故可在O(n)时间内完成任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值