中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

數據結構(03)_順序存儲結構線性表

發布時間:2020-07-13 04:42:35 來源:網絡 閱讀:461 作者:三九感冒靈 欄目:編程語言

基于前面實現的數據結構類模板基礎,繼續完成基于順序存儲結構的線性表的實現,繼承關系圖如下:
數據結構(03)_順序存儲結構線性表

1.線性表簡介

1.1.線性表的表現形式

  • 零個多多個數據元素組成的集合
  • 數據元素在位置上是有序排列的
  • 數據元素的個數是有限的
  • 數據元素的類型必須相同

    1.2.線性表的抽象定義、性質

    線性表是具有相同類型的n(>=)個數據元素的有限序列,(a0, a1, a2... an-1),其中ai是表項,n是表長度。
    性質:

  • a0為線性表的第一個元素,只有一個后繼
  • an-1為線性表的最后一個元素,只有一個前驅
  • 其他數據項既有后繼,也有前驅
  • 支持逐項和順序存儲

    1.3.線性表的抽象實現

  • 插入、刪除數據元素
  • 獲取、設置目標位置元素的值
  • 獲取線性表的長度
  • 清空線性表
template <typename T>
class List:public Object
{
protected:
    List(const List&);
    List& operator ==(const List&);

public:
    List(){}
    virtual bool insert(const T& e) = 0;
    virtual bool insert(int i,const T& e) = 0;
    virtual bool remove(int i) = 0;
    virtual bool set(int i,const T& e) = 0;
    virtual bool get(int i,T& e) const  = 0;
    virtual int length() const = 0;
    virtual void clear() = 0;
};

1.4.總結:

線性表是數據元素的有序并且有限的集合,其中的數據元素類型相同,在程序中表現為一個特殊的數據結構,可以使用C++中的抽象類來表示,用來描述排隊關系的問題。

2.線性表的順序存儲結構

2.1.概念和設計思路

定義:
線性表的順序存儲結構,指的是用一段地址連續的存儲單元依次存儲線性表中的數據元素。
數據結構(03)_順序存儲結構線性表
設計思路:
使用一維數組來實現存儲結構:

// 存儲空間:T* m_array; 當前長度:int m_length;
template <typename T>
class SeqList : public List<T>
{
protected:
    T* m_array;
    int m_length;
};

3.SeqList的設計要點

  • 抽象類模板,存儲空間的大小和位置由子類完成;
  • 實現順序存儲結構線性表的關鍵操作(增、刪、查、等);
  • 提供數組操作符重載,方面快速獲取元素;

    3.1SeqList實現

template <typename T>
class SeqList : public List<T>
{
protected:
    T* m_array;      // 順序存儲空間
    int m_length;    // 當前線性長度
public:

    bool insert(int index, const T& e)
    {
        bool ret = ( (index>=0) && (index<=m_length) ); // <= 因為可以插入的點,必然比當前元素多1

        if(ret && ( m_length < capacity() ))    // 當前至少有一個空間可插入
        {
            for(int p=m_length-1; p>=index; p--)
            {
                m_array[p + 1] = m_array[p];
            }

            m_array[index] = e;
            m_length++;
        }
        return ret;
    }

    bool insert(const T& e)
    {
        return insert(m_length, e);
    }

    bool remove(int index)
    {
        bool ret = ( (index>=0) && (index<m_length) );  // 目標位置合法 <m_length

        if(ret)
        {
            for(int p=index; p<m_length-1; p++)        // 注意思考此處的邊界條件
            {
                m_array[p] = m_array[p+1];
            }

             m_length--;
        }

        return ret;
    }

    bool set(int index, const T& e)
    {
        bool ret = ( (index>=0) && (index<m_length) );

        if(ret)
        {
            m_array[index] = e;
        }

        return ret;
    }

    bool get(int index, T& e) const
    {
        bool ret = ( (index>=0) && (index<m_length) );

        if(ret)
        {
            e = m_array[index];
        }

        return ret;
    }

    int length() const
    {
        return m_length;
    }

    void clear()
    {
        m_length = 0;
    }

    // 順序存儲表的數組訪問方式
    T& operator [] (int index)
    {
        if( (index>=0) && (index<m_length) )
        {
            return m_array[index];
        }
        else
        {
            THROW_EXCEPTION(IndexOutOfBoundsException, "index out of range...");
        }
    }

    T operator [] (int index) const
    {
        static_cast<SeqList<T>&>(*this)[index];    // 去除const屬性,然后調用非const版本實現
    }

    // 順序存儲表的的容量
    virtual int capacity() const = 0;
};

4.StaticList和DynamicList

4.1.StaticList的設計要點:

類模板

  • 使用原生數組做為順序存儲空間
  • 使用模板參數決定數組的大小
    template < typename T, int N >
    class StaticList : public SeqList <T>
    {
    protected:
    T m_space[];        // 順序存儲空間,N為模板參數
    public:
    StaticList();       // 指定父類成員的具體值
    int capacity() const;
    };

    4.2. StaticList實現

template < typename T, int N >
class StaticList : public SeqList <T>
{
protected:
    T m_space[N];       // 順序存儲空間,N為模板參數
public:
    StaticList()        // 指定父類成員的具體值
    {
        this->m_array = m_space;
        this->m_length = 0;
    }
    int capacity() const
    {
        return N;
    }
};

4.3.DynamicList的設計要點:

類模板

  • 申請連續堆空間做為順序存儲空間
  • 保證重置順序存儲空間的異常安全性
    函數異常安全的概念:
  • 不允許任何內存泄露,不允許破壞數據
  • 函數異常安全的基本保證:
  • 如果有異常拋出,對象內的任何成員任然能保持有效狀態,沒有數據破話或者資源泄露。
    template < typename T>
    class DynamicList : public SeqList <T>
    {
    protected:
    int capacity;       // 順序存儲空間的大小
    public:
    DynamicList(int capacity);   // 申請空間
    int capacity(void) const         // 返回capacity的值 
    // 重置存儲空間的大小
    void reset(int capacity);
    ~DynamicList();             // 歸還空間
    };

    4.4. DynamicList實現

template <typename T>
class DynamicList : public SeqList<T>
{

protected:
    int m_capacity;
public:
    DynamicList(int capacity)
    {
        this->m_array = new T[capacity];
        if(this->m_array != NULL)
        {
            this->m_length = 0;
            this->m_capacity = capacity;
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create DynamicList object ...");
        }
    }

    int capacity()const
    {
        return m_capacity;
    }

    void resize(int capacity)
    {
        if(capacity != m_capacity)
        {
            T* array = new T[capacity];
            if(array != NULL)
            {
                int length = (this->m_length < capacity ? this->m_length : capacity);
                for(int i=0;i<length;i++)
                {
                    array[i] = this->m_array[i];
                }

                T* temp = this->m_array;
                this->m_array = array;
                this->m_length = length;
                this->m_capacity = capacity;
                delete[] temp;
            }
            else
            {
                THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create DynamicList object ...");
            }
        }
    }

    ~DynamicList()
    {
        delete[] this->m_array;
    }
};

5.順序存儲結構線性表分析

5.1.時間復雜度

順序存儲結構線性表的效率為O(n),主要受其插入和刪除操作的影響(譬如插入操作時,要插入位置之后的數據要向后挪動) 。

5.2.問題

兩個長度相同的順序存儲結構線性表,插入、刪除操作的耗時是否相同?

  • 不相同,對順序存儲結構線性表,其插入、刪除操作的復雜度還取決于存儲的數據類型,譬如一個普通類型和一個字符串類型/類類型就完全不同(對于復雜數據類型,元素之間移動時必然耗時很多)。從這個角度考慮,線性表的效率存在隱患。
    花費多少

    5.3.禁用拷貝構造和賦值操作。

    拷貝構造和賦值操作會導致兩個指針指向同一個地址,導致內存重復釋放。對于容器類型的類,可以考慮禁用拷貝構造和賦值操作。
    原因: 1、對于生活中容器類的東西,我們無法對其進行賦值(譬如生活中我們不可能將杯子中的水進行復制,只能使用另一個杯子重新去獲取等量的水)。
    實現:將拷貝構造和賦值操作函數定義為proteced成員,在類的外部,不能使用。

    protected:
    List(const List&){}
    List& operator = (const List&){}

    5.4.注意事項

    線性表不能直接當做數組來使用
    順序存儲結構線性表提供了數組操作符的重載,可以直接像數組一樣,同過下標直接獲取目標位置的元素,在具體的使用上類似數組,但是本質上不同,不能代替數組使用:

  • 必須先進行插入操作,才能對其內部的數據進行操作。
  • 原生數組是自帶空間的,可以直接操作。
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

高安市| 长兴县| 曲水县| 通山县| 新蔡县| 北安市| 丰顺县| 德保县| 东海县| 松阳县| 揭西县| 浮山县| 新泰市| 北海市| 喜德县| 兴海县| 南皮县| 襄汾县| 原阳县| 霞浦县| 襄樊市| 广东省| 石门县| 潢川县| 浮山县| 江孜县| 福建省| 土默特左旗| 连城县| 哈密市| 佛山市| 星座| 广南县| 云霄县| 平罗县| 江永县| 大洼县| 施秉县| 论坛| 六安市| 且末县|