1. 程式人生 > >【線性表2】線性表的順序實現:順序表

【線性表2】線性表的順序實現:順序表

str contains 比較 重載 ins 而不是 eal 單元 con

順序表簡介

特點:使用一組地址連續的存儲單元依次存儲表中的數據元素,常見的就是使用數組去實現。 表中邏輯相鄰的數據元素,在物理內存上也相鄰。 順序表中的任意數據元素都可隨機訪問,是一種支持隨機訪問,長度自動動態調整的線性表結構。 優點:訪問表中的元素很快,時間復雜度為O(1) 缺點:插入,刪除元素需要移動大量的元素,時間復雜度為O(n) 。 因此如果我們在編程中需要這樣一種線性表數據結構:構造後對元素的訪問操作很頻繁,而很少進行增,刪等元素位置的調整操作,那麽就可以考慮使用順序表。

代碼實現

#include<iostream>
#include
<stdexcept> #include<cstdlib> using namespace std; class ArrayList { private: enum{ INCREMENT_SIZE = 20, //容量不足時,每次增加10個 INIT_CAPACITY = 10 //初始容量20 }; int size; //實際元素個數 int capacity; //容量 int* elements; //
存儲元素的數組的基地址 //確保表的容量至少為 reqCapacity 個。否則就增加容量 。 void ensureCapacity(int reqCapacity) { int* nelements; if(capacity<reqCapacity) { nelements = (int*)realloc(elements,(capacity+INCREMENT_SIZE)*sizeof(int)); if(nelements!=0
) //如果對動態數組的大小調整成功 { elements = nelements; capacity+=INCREMENT_SIZE; } /* else{ //調整失敗 exit(-1); } */ } } public: ArrayList():size(0),capacity(INIT_CAPACITY),elements(0) { elements = (int*)malloc(sizeof(int)*INIT_CAPACITY); } ~ArrayList() { free(elements); } /* * 功能:在表末尾追加元素 */ void append(int e) { ensureCapacity(size+1); elements[size++] = e; } /* * 將新元素e插入為索引為index * 合法的index值為 [0,size] ,當index為size時,不需要移動元素,當index為0時 * 需要移動所有元素。 * **/ bool insert(int index,int e) { if(index>size || index < 0) return false; //索引不合法 ensureCapacity(size+1); for(int i=size-1;i>=index;--i) { elements[i+1] = elements[i]; } elements[index] = e; size++; return true; } /* * 刪除索引為index 的元素 。 * 合法的index值為 [0,size-1] ,當index=0時,刪除的是第一個元素。 * 當index為size-1時,刪除的是最後一個元素 **/ bool remove(int index) { if(index>=size || index <0) return false; //索引不合法 for(int i=index;i<size-1;++i) { elements[i] = elements[i+1]; } size --; return true; } /* * 功能:查找一個元素在表中的索引,如果不存在此元素,則返回-1 */ int indexOf(int e) const { for(int i=0;i<size;++i) { if(elements[i] == e) return i; } return -1; } /* * 功能:判斷表中是否包含某個元素。 */ bool contains(int e) const { return (-1 != indexOf(e)); } int length() const { return size; } void clear() { size = 0; } bool isEmpty()const { return size==0; } void show()const { cout<<"["; for(int i=0;i<size;++i) { if(i!=0) cout<<,; cout<<elements[i]; } cout<<"]"; } //重載索引運算符[],元素只讀版本 int operator[](int index) const { if(index >=size || index < 0) //如果索引不合法 ,則拋異常 throw std::out_of_range(0); return elements[index]; } //重載索引運算符[],元素可讀可寫版本 int& operator[](int index) { if(index >=size || index < 0) throw std::out_of_range(0); return elements[index]; } }; //end class int main() { ArrayList list1; list1.append(1); list1.append(2); list1.append(5); list1.insert(0,100); list1.remove(2); list1.show(); return 0; }

順序表的短板

插入元素,時間復雜度 O(n)

插入為 第 i 個 元素,則需要移動 n - i +1 個數據元素. 需要移動 第 n 到第 i 個 元素。 均值的計算: 一共為 (n+1)(n+0) / 2 ,因為一共計算插了 n+1 個位置。則均值為 : n / 2
插為第 i 個 元素 1 2 ... n+1
移動 元素的個數 n n-1 ... 0
刪除元素,時間復雜度 O(n) 刪除 第 i 個 元素,則需要移動 n - i 個數據元素 。 需要移動 第 i+ 1 到 第 n 個 元素。 均值的計算:一共為 (n)(n-1+0) / 2 ,因為一共計算刪除 n 個位置。則均值為 : (n-1) / 2
刪除第 i 個 元素 1 2 ... n
移動 元素的個數 n-1 n-2 ... 0

小提示

1、一般在實際開發時,為了盡量避免移動元素的開銷,都會使用貼近硬件的API去完成內存數據的移動,而不是使用循環。例如使用memmove函數。 2、當內部數組的容量不夠時,需要重新調整數組的大小,上面的例子我們使用了realloc函數去實現,且每次增加20。然而我們必須認識到,調整大小是很銷耗資源的一個操作,因此在實際開發時,我們必須做出明智的容量增長策略。例如:Java中的ArrayList每次將容量擴展為原來的1.5倍。
編程語言中的實現類 增長因子
Java ArrayList 1.5 (3/2)
Python PyListObject ~1.125 (n + n >> 3)
VC++ 2013 1.5 (3/2)
G++ 5.2.0 2
Clang 3.6 2

編程練習

將2個非遞減排序的順序表合並為1個表,且新表也保持非遞減排序。

如 [1,56,88 ] 和 [ 2,75] 合並後為 [ 1,2,56,75,88 ]

#include<iostream>
#include<stdexcept>     
#include<cstdlib>
using namespace std;
class ArrayList
{
private:
     enum{ INCREMENT_SIZE = 20,    //容量不足時,每次增加10個
           INIT_CAPACITY = 10      //初始容量20
         };
     int   size;                  //實際元素個數
     int   capacity;              //容量
     int*  elements;              //存儲元素的數組的基地址
    //確保表的容量至少為 reqCapacity 個。否則就增加容量 。
     void ensureCapacity(int reqCapacity)
     {
         int* nelements;
         if(capacity<reqCapacity)
         {   
             nelements = (int*)realloc(elements,(capacity+INCREMENT_SIZE)*sizeof(int));
             
             if(nelements!=0)   //如果對動態數組的大小調整成功
             {  
               elements = nelements;
               capacity+=INCREMENT_SIZE;
             }
             /*
              else{            //調整失敗
                 exit(-1);
             }
             */
         }
     }
     
public:
    ArrayList():size(0),capacity(INIT_CAPACITY),elements(0)
    {
        elements = (int*)malloc(sizeof(int)*INIT_CAPACITY);
    }   
    ~ArrayList()
    {
        free(elements);
    }
    /*
    * 功能:在表末尾追加元素
    */
    void append(int e)
    {
        ensureCapacity(size+1);
        elements[size++]  = e;
    }
    
    
    /*
    * 將新元素e插入為索引為index
    * 合法的index值為  [0,size] ,當index為size時,不需要移動元素,當index為0時
    * 需要移動所有元素。
    *
    **/
    bool insert(int index,int e)
    {   
        if(index>size || index < 0) return false;  //索引不合法
        ensureCapacity(size+1);
    
        for(int i=size-1;i>=index;--i)
        {
            elements[i+1] = elements[i];
        }   
       
          
          elements[index] = e;
        size++;
         return true;
          
    }
    
    
    
    /*
    * 刪除索引為index 的元素 。
    * 合法的index值為  [0,size-1] ,當index=0時,刪除的是第一個元素。
    * 當index為size-1時,刪除的是最後一個元素
    **/
    bool remove(int index)
    {
        if(index>=size || index <0) return false;    //索引不合法
        for(int i=index;i<size-1;++i)
        {
            elements[i] = elements[i+1];
        }
        size --;
        return true;
    }
    
    
    /*
    * 功能:查找一個元素在表中的索引,如果不存在此元素,則返回-1
    */
    int indexOf(int e) const
    {
        for(int i=0;i<size;++i)
        {
            if(elements[i] == e)
                return i;
        }
        return -1;
    }
    
    /*
    * 功能:判斷表中是否包含某個元素。
    */
    bool contains(int e) const
    {
        return (-1 != indexOf(e));
    }
    
    int length() const
    {
        return size;
    }
    
    void clear()
    {
        size = 0;
    }
    
    bool isEmpty()const
    {
        return size==0;
    }
    void show()const
    {
        cout<<"[";   
        for(int i=0;i<size;++i)
        {
            if(i!=0) cout<<,;
            cout<<elements[i];
        }
        cout<<"]";   
    }
    //重載索引運算符[],元素只讀版本
    int operator[](int index) const
    {
        if(index >=size || index < 0)          //如果索引不合法 ,則拋異常
            throw std::out_of_range(0);
        return elements[index];   
    }
    //重載索引運算符[],元素可讀可寫版本
    int& operator[](int index)
    {
        if(index >=size || index < 0)
            throw std::out_of_range(0);
        return elements[index];
    }
}; //end class
/*
* 功能:將2個非遞減排序的順序表合並為1個表re,且re表也保持非遞減排序
*/
void MergeList(const ArrayList& list1,const ArrayList& list2,ArrayList&re)
{
    int i=0,j=0;    //用於訪問list1和list2的索引
    int k=0;        //訪問re的索引
    int e1,e2;      //保存從list1和list2中提出的元素
    
    while(i<list1.length() && j<list2.length())
    {
        e1 = list1[i];
        e2 = list2[j];
        if(e1 <= e2)      //比較大小,將小的元素加入到re表中。
        {
            re.append(e1);
            i++;
        }
        else
        {
            re.append(e2);
            j++;
        }        
        k++;
    }    
    
    //如果list1還沒訪問完
    while(i<list1.length())
    {
        re.append( list1[i] );
        i++;
        k++;
    }
    //如果list2還沒訪問完
    while(j<list2.length())
    {
        re.append( list2[j] );
        j++;
        k++;
    }
    
}
int main()
{
    ArrayList list1;
    ArrayList list2;
    ArrayList re;
    list1.append(12);
    list1.append(35);
    list1.append(88);
    
    list2.append(1);
    list2.append(2);
    list2.append(7);
    list2.append(82);
    list2.append(101);
    
    MergeList(list1,list2,re);
    
    re.show();
    
    return 0;
}

技術分享

【線性表2】線性表的順序實現:順序表