日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构开发(3):线性表的顺序存储结构

發布時間:2024/7/19 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构开发(3):线性表的顺序存储结构 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

0.目錄

1.線性表的本質和操作

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

3.順序存儲結構的抽象實現和具體實現

  • 3.1 SeqList
  • 3.2 StaticList 和 DynamicList

4.順序存儲線性表的分析

  • 4.1 效率分析
  • 4.2 功能分析

5.小結

1.線性表的本質和操作

線性表 ( List ) 的表現形式:

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

線性表 ( List ) 的抽象定義——線性表是具有相同類型的n(≥0)個數據元素的有限序列:

線性表 ( List ) 的性質:

線性表只是一個單純的概念嗎?如何在程序中描述和使用一個線性表?

線性表的一些常用操作:

  • 將元素插入線性表
  • 將元素從線性表中刪除
  • 獲取目標位置處元素的值
  • 設置目標位置處元素的值
  • 獲取線性表的長度
  • 清空線性表

線性表在程序中表現為一種特殊的數據類型:

(在StLib中實現List.h)

#ifndef LIST_H #define LIST_H#include "Object.h"namespace StLib {template <typename T> class List : public Object { public: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; };}#endif // LIST_H

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

順序存儲的定義——線性表的順序存儲結構,指的是用一段地址連續的存儲單元依次存儲線性表中的數據元素。

設計思路——可以用一維數組來實現順序存儲結構:

  • 存儲空間:T* m_array;
  • 當前長度:int m_length;

順序存諸結構的元素獲取操作:

  • 判斷目標位置是否合法
  • 將目標位置作為數組下標獲取元素

順序存儲結構的元素插入操作:

  • 判斷目標位置是否合法
  • 將目標位置之后的所有元素后移一個位置
  • 將新元素插入目標位置
  • 線性表長度加 1
  • 順序存儲結構的元素插入示例:

    順序存儲結構的元素刪除操作:

  • 判斷目標位置是否合法
  • 將目標位置后的所有元素前移一個位置
  • 線性表長度減 1
  • 順序存儲結構的元素刪除示例:

    3.順序存儲結構的抽象實現和具體實現

    3.1 SeqList

    本節目標:

    • 完成順序存儲結構線性表的抽象實現

    SeqList設計要點:

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

    (在StLib中實現SeqList.h)

    #ifndef SEQLIST_H #define SEQLIST_H#include "List.h" #include "Exception.h"namespace StLib {template <typename T> class SeqList : public List<T> { protected:T* m_array; // 順序存儲空間int m_length; // 當前線性表長度 public:bool insert(int i, const T& e){bool ret = ( (0 <= i) && (i <= m_length) );ret = ret && ( (m_length + 1) <= capacity() );if( ret ){for(int p=m_length-1; p>=i; p--){m_array[p+1] = m_array[p];}m_array[i] = e;m_length++;}return ret;}bool remove(int i){bool ret = ( (0 <= i) && (i <= m_length) );if( ret ){for(int p=i; p<m_length-1; p++){m_array[p] = m_array[p+1];}m_length--;}return ret;}bool set(int i, const T& e){bool ret = ( (0 <= i) && (i < m_length) );if( ret ){m_array[i] = e;}return ret;}bool get(int i, T& e) const{bool ret = ( (0 <= i) && (i < m_length) );if( ret ){e = m_array[i];}return ret;}int length() const{return m_length;}void clear(){m_length = 0;}// 順序存儲線性表的數組訪問方式T& operator[] (int i){if( (0 <= i) && (i < m_length) ){return m_array[i];}else{THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid ...");}}T operator[] (int i) const{return (const_cast<SeqList<T>&>(*this))[i];}// 順序存儲空間的容量virtual int capacity() const = 0; };}#endif // SEQLIST_H

    3.2 StaticList 和 DynamicList

    本節目標:

    • 完成 StaticList 類的具體實現
    • 完成 DynamicList 類的具體實現

    StaticList 設計要點:

    • 類模板
    • 使用原生數組作為順序存儲空間
    • 使用模板參數決定數組大小

    (在StLib中實現StaticList.h)

    #ifndef STATICLIST_H #define STATICLIST_H#include "SeqList.h"namespace StLib {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;} };}#endif // STATICLIST_H

    main.cpp測試

    #include <iostream> #include "StaticList.h" #include "Exception.h"using namespace std; using namespace StLib;int main() {StaticList<int, 5> l;for(int i=0; i<l.capacity(); i++){l.insert(0, i);}for(int i=0; i<l.capacity(); i++){cout << l[i] << endl;}l[0] *= l[0];for(int i=0; i<l.capacity(); i++){cout << l[i] << endl;}try{l[5] = 5;}catch(const Exception& e){cout << e.message() << endl;cout << e.location() << endl;}return 0; }

    運行結果為:

    4 3 2 1 0 16 3 2 1 0 Parameter i is invalid ... f:\allcode\qtcreator\datastructure\stlib\SeqList.h:97

    DynamicList 設計要點:

    • 類模板
    • 申請連續堆空間作為順序存儲空間
    • 動態設置順序存儲空間的大小
    • 保證重置順序存儲空間時的異常安全性
    • 函數異常安全的概念
    • 不泄漏任何資源
    • 不允許破壞數據
    • 函數異常安全的基本保證
    • 如果異常被拋出
    • 對象內的任何成員仍然能保持有效狀態
    • 沒有數據的破壞及資源泄漏

    (在StLib中實現DynamicList.h)

    #ifndef DYNAMICLIST_H #define DYNAMICLIST_H#include "SeqList.h"namespace StLib {template <typename T> class DynamicList : public SeqList<T> { protected:T 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 resize DynamicList object ...");}}}~DynamicList() // 歸還空間{delete[] this->m_array;} };}#endif // DYNAMICLIST_H

    main.cpp測試

    #include <iostream> #include "DynamicList.h" #include "Exception.h"using namespace std; using namespace StLib;int main() {DynamicList<int> l(5);for(int i=0; i<l.capacity(); i++){l.insert(0, i);}for(int i=0; i<l.length(); i++){cout << l[i] << endl;}cout << endl;l[0] *= l[0];for(int i=0; i<l.length(); i++){cout << l[i] << endl;}try{l[5] = 5;}catch(const Exception& e){cout << e.message() << endl;cout << e.location() << endl;l.resize(10);l.insert(5, 50);}l[5] = 5;for(int i=0; i<l.length(); i++){cout << l[i] << endl;}cout << endl;l.resize(3);for(int i=0; i<l.length(); i++){cout << l[i] << endl;}return 0; }

    運行結果為:

    4 3 2 1 016 3 2 1 0 Parameter i is invalid ... f:\allcode\qtcreator\datastructure\stlib\SeqList.h:97 16 3 2 1 0 516 3 2

    問題:
    是否可以將 DynamicList 作為 StaticList 的子類實現?
    (不能將 DynamicList 作為 StaticList 的子類實現,反之也是不可以的,因為這兩個類對于順序存儲空間的指定是截然不同沒有任何關系的,因此它們兩個的地位必然是位于同一層次的。)

    4.順序存儲線性表的分析

    4.1 效率分析

    效率分析:

    問題:
    長度相同的兩個SeqList插入刪除操作的平均耗時是否相同?
    (insert操作最耗時的部分是for循環,究竟有多耗時取決于線性表里面存儲的數據元素的類型是什么。如果存儲的數據元素的類型是一個自定義的類,并且這個類還非常的龐大,那么插入操作就真的非常耗時了,因為涉及了對象之間的拷貝。)

    4.2 功能分析

    下面的代碼正確嗎?為什么?

    下面的代碼正確嗎?為什么?

    功能分析:
    對于容器類型的類,可以考慮禁用拷貝構造和賦值操作。

    代碼優化(List.h和SeqList.h):
    優化List.h

    #ifndef LIST_H #define LIST_H#include "Object.h"namespace StLib {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; };}#endif // LIST_H

    優化SeqList.h

    #ifndef SEQLIST_H #define SEQLIST_H#include "List.h" #include "Exception.h"namespace StLib {template <typename T> class SeqList : public List<T> { protected:T* m_array; // 順序存儲空間int m_length; // 當前線性表長度 public:bool insert(int i, const T& e){bool ret = ( (0 <= i) && (i <= m_length) );ret = ret && ( (m_length + 1) <= capacity() );if( ret ){for(int p=m_length-1; p>=i; p--){m_array[p+1] = m_array[p];}m_array[i] = e;m_length++;}return ret;}bool insert(const T& e){return insert(m_length, e);}bool remove(int i){bool ret = ( (0 <= i) && (i <= m_length) );if( ret ){for(int p=i; p<m_length-1; p++){m_array[p] = m_array[p+1];}m_length--;}return ret;}bool set(int i, const T& e){bool ret = ( (0 <= i) && (i < m_length) );if( ret ){m_array[i] = e;}return ret;}bool get(int i, T& e) const{bool ret = ( (0 <= i) && (i < m_length) );if( ret ){e = m_array[i];}return ret;}int length() const{return m_length;}void clear(){m_length = 0;}// 順序存儲線性表的數組訪問方式T& operator[] (int i){if( (0 <= i) && (i < m_length) ){return m_array[i];}else{THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid ...");}}T operator[] (int i) const{return (const_cast<SeqList<T>&>(*this))[i];}// 順序存儲空間的容量virtual int capacity() const = 0; };}#endif // SEQLIST_H

    main.cpp測試

    #include <iostream> #include "DynamicList.h"using namespace std; using namespace StLib;int main() {DynamicList<int> l(5);for(int i=0; i<l.capacity(); i++){l.insert(i);}for(int i=0; i<l.length(); i++){cout << l[i] << endl;}return 0; }

    運行結果為:

    0 1 2 3 4

    下面的代碼正確嗎?為什么?

    問題分析:
    順序存儲結構線性表提供了數組操作符重載,通過重載能夠快捷方便的獲取目標位置處的數據元素,在具體的使用形式上類似數組,但是由于本質不同,不能代替數組使用

    5.小結

    • 線性表是數據元素的有序并且有限的集合
    • 線性表中的數據元素必須是類型相同的
    • 線性表可用于描述排隊關系的問題
    • 線性表在程序中表現為一種特殊的數據類型
    • 線性表在C++中表現為一個抽象類
    • StaticList 通過模板參數定義順序存儲空間
    • DynamicList 通過動態內存申請定義順序存諸空間
    • DynamicList 支持動態重置順序存儲空間的大小
    • Dynamiclist 中的 resize() 函數實現需要保證異常安全
    • 順序存儲線性表的插入和刪除操作存在重大效率隱患
    • 線性表作為容器類,應該避免拷貝構造和拷貝賦值
    • 順序存儲線性表可能被當成數組誤用
    • 工程開發中可以考慮使用數組類代替原生數組使用

    轉載于:https://www.cnblogs.com/PyLearn/p/10114009.html

    總結

    以上是生活随笔為你收集整理的数据结构开发(3):线性表的顺序存储结构的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。