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

二者的時間複雜度均爲常數

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