Day11

昨天向量那章没看完,今天继续看

常规向量

书中实现了一个向量类的基本接口的方法,在此记录一下

置乱方法

template<typname T> void permute(Vector<T>& v)
{
    for(int i = v.size; i > 0; i--)
    {
        swap(v[i-1], v[rand() % i]);   
        //置换第i-1个元素与下标范围在[0, i)间的任意一个元素 
    }
}

置乱某个区间的向量

template<typename T> void Vector<T>::permute(Rank lo, Rank hi)
{
    T* v = _elem + lo; 
    //将子向量_elem[lo, hi]视为新向量v[0, hi - lo]
    for(Rank i = hi - lo; i > 0; i--)
    {
        swap(v[i], v[rand() % i]);  
    }
}

时间复杂度为O(n)。

无序向量:支持比对(判等),未必支持比较(大小)的向量。
顺序查找:逐个比对查找的方式。最好情况为O(1),最坏情况为O(n)。

template<typename T> Rank Vector<T>::find(const* e, Rank lo, Rank hi)
{
    while((lo < hi --) && (e != _elem[hi])){ }
    return hi;
}

插入:在位置r插入元素e:将n到r元素依次后移,将元素e赋值到位置r上。

template<typname T> void Vector<T>::insert(Rank r, const& e)
{
    expand();   //如果有必要需要扩展数组
    for(int i = size; i > 0; i--)
    {
        _elem[i] = _elem[i - 1];    
    }
    _elem[r] = e;
    size++;
}

删除:删除从lo到hi的元素:依次将从hi到n的元素赋值给从lo开始的地址。

template<typename T> void Vector<T>::remove(Rank lo, Rank hi)
{
    if(hi > size) reuturn;
    whil(hi < size)
    {
        _elem[lo++] = _elem[hi++];  
    }
    size = size - hi + lo;
    shrink();  //如果有必要需要缩小数组空间
}

去重:每次在范围[0, i)内查找是否包含元素v[i],如果不包含则 i++,如果包含则删除v[i]。由于同时包含了查找和删除,二者的时间复杂度分别为O(n),所以去重的总时间复杂度为O(n(2))。

有序向量

所有元素按照线性次序存放,并且这些元素的数值也按照此次序单调分布,称为有序向量。
由于不要求元素互异,通常约定非降序序列为
对于任意 0<= i < j < n 都有 V[i] <= V[j]。

由于有序向量的特性,针对于有序向量的去重,如果还是用和无序向量中相同的去重方法则效率太低,所以有序向量中的去重利用有序向量的特性,设置两个动态下标同时进行比较和替换,当两个值不同时,将后一个值移到前一个值之后,最后直接截掉遍历结束后尾部多余的元素。

template<typename T> void Vector<T>::uniquify()
{
    Rank i = 0; 
    Rank j = 0;
    while(++j < size)
    {
        if(_elem[i] != _elem[j])
        {
            _elem[i++] = _elem[j];  
        }   
    }
    size = i++;
    shrink();
}

列表

元素也构成线性逻辑次序,但是元素的物理地址可以任意。“循位置访问”/“循链接访问”。

链表:典型动态存储结构。其中的数据分散为一系列节点,节点和节点之间通过指针相互索引和访问。
列表结构

默认构造方法,需运行常数时间

template<typename T> void List<T>::init()
{
    header = new ListNode<T>;
    trailer = new ListNode<T>;
    header -> succ = trailer;
    header -> pred = null;
    trailer -> succ = null;
    trailer -> pred = header;
    size = 0;
}

查找,时间复杂度为O(n)

template<typename T> ListNodePosi<T> List<T>::find(T const& e, int n, ListNodePosi<T> p)
{
    while(n-- > 0)
    {
        if(e == (p = p -> pred) -> data)
        {
            return p;
        }
    }
    return null;
}

前插入(在当前节点this前插入)

template<typename T> ListNodePosi<T> List<T>::InsertAsPred(T const& e)
{
    ListNodePosi(T) x = new List(e, pred, this);
    pred -> succ = x;      //前结点的后继为x
    pred = x;              //当前结点的前驱为x
    return x;
}

后插入

template<typename T> ListNodePosi<T> List<T>::InsertAsSucc(T const& e)
{
    ListNodePosi(T) x = new List(e, this, succ);
    succ -> pred = x;
    succ = x;
    return x;
}

二者的时间复杂度均为常数

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章