幼儿园老师总会让小朋友以同样的排队秩序出行。



线性表只是一个单纯的概念吗?如何在程序中描述和使用一个线性表?

List.h
- #ifndef LIST_H_
- #define LIST_H_
- /*******************************************************************************
- * Include Files *
- *******************************************************************************/
- #include "Object.h"
- /*******************************************************************************
- * Type Definition *
- *******************************************************************************/
- namespace DTLib
- {
-
- template < typename T >
- class List : public Object
- {
- protected:
- List(const List<T>&); // 拷贝构造函数 对于容器类型的类,可以考虑禁用拷贝构造和赋值操作。
- List<T>& operator= (const List<T>&); // 赋值操作符重载函数 对于容器类型的类,可以考虑禁用拷贝构造和赋值操作。
- public:
- List() { } // 构造函数
- virtual bool insert(const T& e) = 0; // 在线性表尾部插入e
- virtual bool insert(int i, const T& e) = 0; // 在i处插入e
- virtual bool remove(int i) = 0; // 删除第i个元素
- virtual bool set(int i, const T& e) = 0; // 设置第i个元素为e
- virtual bool get(int i, T& e) const = 0; // 获取第i个元素为e
- virtual int find(const T& e) const = 0; // 查找指定的元素
- virtual int length() const = 0; // 返回当前有效值的数量
- virtual void clear() = 0; // 清空链表
-
- List<T>& self()
- {
- return *this;
- }
- };
-
- }
-
-
- #endif // LIST_H_
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表中的数据元素。



通过数组下标获取元素

1. 判断目标位置是否合法
2. 将目标位置之后的所有元素后移一个位置
3. 将新元素插入目标位置
4. 线性表长度加1

线性表长度+1 ===> 会不会越界;
插入的位置是否合理(不能插入的位置前后都没数据)

1. 判断目标位置是否合法
2. 将目标位置后的所有元素前移一个位置
3. 线生表长度减1

删除的位置是否合理(不能删除的位置没数据)

To be continued …

完成顺序存储结构线性表的抽象实现


SeqList.h
- #ifndef SEQLIST_H_
- #define SEQLIST_H_
- /*******************************************************************************
- * Include Files *
- *******************************************************************************/
- #include "List.h"
- #include "Exception.h"
- /*******************************************************************************
- * Type Definition *
- *******************************************************************************/
- namespace DTLib
- {
-
- template < typename T >
- class SeqList : public List<T>
- {
- protected:
- T* m_array; // 数组地址
- int m_length; // 当前线性表长度
- public:
- /**********************************************************************
- * Function: insert()
- * Description: 在i位置,插入e
- * Input: i 待插入的位置
- * e 待插入的数据
- * Output:
- * Return: bool 是否插入成功
- * Others: O(n+5) => O(n)
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- bool insert(int i, const T& e)
- {
- bool ret = ((0 <= i) && (i <= m_length)); // i的合法性 (不能插入的位置前后都没数据)
-
- ret = ret && (m_length < 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++; // 线性表长度+1
- }
-
- return ret;
- }
-
- /**********************************************************************
- * Function: insert()
- * Description: 在线性表尾部,插入e
- * Input: e 待插入的数据
- * Output:
- * Return: bool 是否插入成功
- * Others: O(n)
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- bool insert(const T& e)
- {
- return insert(m_length, e);
- }
-
- /**********************************************************************
- * Function: remove()
- * Description: 删除i位置的元素
- * Input: i 待删除的位置
- * Output:
- * Return: bool 是否删除成功
- * Others: O(n)
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- bool remove(int i)
- {
- bool ret = ((0 <= i) && (i < m_length)); // i的合法性
-
- if( ret )
- {
- for(int p=i; p<m_length-1; p++) // 将目标位置后的所有元素前移一个位置
- {
- m_array[p] = m_array[p+1];
- }
-
- m_length--; // 线性表长度-1
- }
-
- return ret;
- }
- /**********************************************************************
- * Function: set()
- * Description: 更新i位置的元素
- * Input: i 待更新的位置
- * e 待更新的数据
- * Output:
- * Return: bool 是否更新成功
- * Others:
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- bool set(int i, const T& e)
- {
- bool ret = ((0 <= i) && (i < m_length)); // i的合法性
-
- if( ret )
- {
- m_array[i] = e; // 更新数据
- }
-
- return ret;
- }
-
- /**********************************************************************
- * Function: get()
- * Description: 获取i位置的元素
- * Input: i 待获取的位置
- * Output: e 获取的元素
- * Return: bool 是否获取成功
- * Others: O(n)
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- bool get(int i, T& e) const
- {
- bool ret = ((0 <= i) && (i < m_length)); // i的合法性
-
- if( ret )
- {
- e = m_array[i]; // 获取数据
- }
-
- return ret;
- }
-
- /**********************************************************************
- * Function: find()
- * Description: 查找指定的元素
- * Input: i 待寻找的元素
- * Output:
- * Return: int 元素的位置
- * Others: O(n)
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- int find(const T& e) const
- {
- int ret = -1;
-
- for(int i=0; i<m_length; i++) // 遍历寻找
- {
- if( m_array[i] == e )
- {
- ret = i;
- break;
- }
- }
-
- return ret;
- }
-
- /**********************************************************************
- * Function: length()
- * Description: 返回当前线性表的所用数量
- * Input:
- * Output:
- * Return: int 当前线性表的所用数量
- * Others:
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- int length() const
- {
- return m_length;
- }
-
- /**********************************************************************
- * Function: clear()
- * Description: 清空链表
- * Input:
- * Output:
- * Return:
- * Others:
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- void clear()
- {
- m_length = 0;
- }
-
- /**********************************************************************
- * Function: operator[]()
- * Description: []操作符重构函数
- * Input: i 待返回的元素位置
- * Output:
- * Return: T 元素的值
- * Others: 数组访问方式
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- T& operator[] (int i)
- {
- if( (0 <= i) && (i < m_length) ) // i的合法性
- {
- return m_array[i];
- }
- else
- {
- THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid ...");
- }
- }
- /**********************************************************************
- * Function: operator[]()
- * Description: []操作符重构函数(const类型的对象使用)
- * Input: i 待返回的元素位置
- * Output:
- * Return: T 元素的值
- * Others: 该函数调用了上一个[]操作符重构函数
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- T operator[] (int i) const
- {
- return (const_cast<SeqList<T>&>(*this))[i];
- }
-
- /**********************************************************************
- * Function: capacity()
- * Description: 顺序存储空间的容量
- * Input:
- * Output:
- * Return: int 顺序存储空间的容量
- * Others: 纯虚函数
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- virtual int capacity() const = 0;
- };
-
-
- }
-
- #endif // SEQLIST_H_


· 
StaticList.h
- #ifndef STATICLIST_H_
- #define STATICLIST_H_
- /*******************************************************************************
- * Include _Files *
- *******************************************************************************/
- #include "SeqList.h"
- /*******************************************************************************
- * Type Definition *
- *******************************************************************************/
- namespace DTLib
- {
-
- template < typename T, int N >
- class StaticList : public SeqList<T>
- {
- protected:
- T m_space[N]; // 元素总数量
- public:
- StaticList() // 构造函数 - 指定父类成员的具体值
- {
- this->m_array = m_space; // 初始化元素总数量
- this->m_length = 0; // 初始化当前线性表长度
- }
-
- int capacity() const // 获取元素总数量
- {
- return N;
- }
- };
-
-
- }
-
- #endif // STATICLIST_H_

DynamicList.h
- #ifndef DYNAMICLIST_H_
- #define DYNAMICLIST_H_
- /*******************************************************************************
- * Include _Files *
- *******************************************************************************/
- #include "SeqList.h"
- #include "Exception.h"
- /*******************************************************************************
- * Type Definition *
- *******************************************************************************/
- namespace DTLib
- {
-
- template < typename T >
- class DynamicList : public SeqList<T>
- {
- protected:
- int m_capacity; // 元素总数量
- public:
- /**********************************************************************
- * Function: DynamicList()
- * Description: 构造函数
- * Table Accessed:
- * Table Updated:
- * Input: capacity 元素总数量
- * Output:
- * Return:
- * Others:
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- 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 ...");
- }
- }
- /**********************************************************************
- * Function: capacity()
- * Description: 返回元素总数量
- * Table Accessed:
- * Table Updated:
- * Input:
- * Output:
- * Return: int 返回 元素总数量
- * Others:
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- int capacity() const
- {
- return m_capacity;
- }
-
- /**********************************************************************
- * Function: resize()
- * Description: 重新设置元素数量
- * Table Accessed:
- * Table Updated:
- * Input: capacity 新元素总数量
- * Output:
- * Return:
- * Others:
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- 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++) // 将length个元素复制到新申请的堆空间中
- {
- array[i] = this->m_array[i]; /* 此可能发生异常,动态链表依然可用,但是会发生内存泄漏。且无法避免。*/
- } /* T是一个泛型类型,赋值操作符可能被重载,并且重载的实现出现的异常,上层修改即可*/
-
- 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 ...");
- }
- }
- }
- /**********************************************************************
- * Function: ~DynamicList()
- * Description: 析构函数
- * Table Accessed:
- * Table Updated:
- * Input:
- * Output:
- * Return:
- * Others: 释放堆内存空间
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- ~DynamicList()
- {
- delete[] this->m_array;
- }
- };
-
-
- }
-
- #endif // DYNAMICLIST_H_
是否可以将DynamicList 作为StaticList的子类实现?

长度相同的两个SeqList,插入和删除操作的平均耗时是否相同?
要具体问题具体分析。


拷贝使得两个对象指向同一份堆空间,导致同一个堆空间被两次。
对于容器类型的类,可以考虑禁用拷贝构造和赋值操作。

禁用拷贝构造和赋值操作。

线性表必须先插入元素,才能使用操作符[]访问元素。
顺序存储结构线性表提供了数组操作符重载,通过重载能够快捷方便的获取目标位置处的数据元素,在具体的使用形式上类似数组,但是由于本质不同,不能代替数组使用。



Array.h
- #ifndef ARRAY_H_
- #define ARRAY_H_
- /*******************************************************************************
- * Include Files *
- *******************************************************************************/
- #include "Object.h"
- #include "Exception.h"
- /*******************************************************************************
- * Type Definition *
- *******************************************************************************/
- namespace DTLib
- {
-
- template < typename T >
- class Array : public Object
- {
- protected:
- T* m_array;
- public:
- /**********************************************************************
- * Function: set()
- * Description: 设置数组下标为i的元素值为e
- * Input: i 下标为i
- * e 元素值为e
- * Output:
- * Return: bool 返回是否成功
- * Others: 与原生数组差异:预防下标越界
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- virtual bool set(int i, const T& e)
- {
- bool ret = ((0 <= i) && (i < length()));
-
- if( ret )
- {
- m_array[i] = e;
- }
-
- return ret;
- }
-
- /**********************************************************************
- * Function: get()
- * Description: 获取数组下标为i的元素值
- * Input: i 下标为i
- * e 元素值为e
- * Return: bool 返回是否成功
- * Others: 与原生数组差异:预防下标越界
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- virtual bool get(int i, T& e) const
- {
- bool ret = ((0 <= i) && (i < length()));
-
- if( ret )
- {
- e = m_array[i];
- }
-
- return ret;
- }
-
- /**********************************************************************
- * Function: operator[]()
- * Description: []操作符重载函数
- * Input: i 数组下标i的元素
- * Output:
- * Return: T 返回元素的值
- * Others: 下标越界,抛出异常
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- virtual T& operator[] (int i)
- {
- if((0 <= i) && (i < length()))
- {
- return m_array[i];
- }
- else
- {
- THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid ...");
- }
- }
-
- /**********************************************************************
- * Function: operator[]()
- * Description: []操作符重载函数(传入const)
- * Input: i 数组下标i的元素
- * Output:
- * Return: T 返回元素的值
- * Others: 下标越界,抛出异常
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- virtual T operator[] (int i) const
- {
- return (const_cast<Array<T>&>(*this))[i];
- }
-
- /**********************************************************************
- * Function: array()
- * Description: 返回数组的地址
- * Input:
- * Output:
- * Return: T 返回数组的地址
- * Others:
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- T* array() const
- {
- return m_array;
- }
-
- Array<T>& self()
- {
- return *this;
- }
-
- virtual int length() const = 0;
- };
-
- }
-
- #endif // ARRAY_H_

StaticArray.h
- #ifndef STATICARRAY_H_
- #define STATICARRAY_H_
- /*******************************************************************************
- * Include Files *
- *******************************************************************************/
- #include "Array.h"
- /*******************************************************************************
- * Type Definition *
- *******************************************************************************/
- namespace DTLib
- {
-
- template < typename T, int N >
- class StaticArray : public Array<T>
- {
- protected:
- T m_space[N];
- public:
- StaticArray() // 构造函数
- {
- this->m_array = m_space; // 初始化父类成员
- }
-
- StaticArray(const StaticArray<T, N>& obj) // 拷贝构造函数
- {
- this->m_array = m_space; // 初始化父类成员
-
- for(int i=0; i<N; i++) // 循环赋值
- {
- m_space[i] = obj.m_space[i];
- }
- }
-
- StaticArray<T, N>& operator= (const StaticArray<T, N>& obj) // 赋值构造函数
- {
- if( this != &obj ) // 不允许自赋值
- {
- for(int i=0; i<N; i++) // 循环赋值
- {
- m_space[i] = obj.m_space[i];
- }
- }
-
- return *this; // 返回当前类的指针,代表允许连续赋值
- }
-
- int length() const // 返回数组的成员数量
- {
- return N;
- }
- };
-
-
- }
-
- #endif // STATICARRAY_H_
To be continued …

完成DynamicArray 类的具体实现


DynamicArray类中的函数实现存在重复的逻辑,如何进行代码优化?
DynamicArray.h
- #ifndef DYNAMICARRAY_H_
- #define DYNAMICARRAY_H_
- /*******************************************************************************
- * Include _Files *
- *******************************************************************************/
- #include "Array.h"
- #include "Exception.h"
- /*******************************************************************************
- * Type Definition *
- *******************************************************************************/
- namespace DTLib
- {
-
- template < typename T >
- class DynamicArray : public Array<T>
- {
- protected:
- int m_length;
-
- /**********************************************************************
- * Function: copy()
- * Description: 动态调整数组大小
- * Input: array 数组类地址
- * len 原数组成员数量
- * newLen 新数组成员数量
- * Output:
- * Return: bool 返回数组类地址
- * Others: O(n)
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- T* copy(T* array, int len, int newLen)
- {
- T* ret = new T[newLen];
-
- if( ret != NULL )
- {
- int size = (len < newLen) ? len : newLen; // 取数组成员数量小的,进行数组拷贝
-
- for(int i=0; i<size; i++)
- {
- ret[i] = array[i];
- }
- }
-
- return ret;
- }
-
- /**********************************************************************
- * Function: update()
- * Description: 动态调整后更新
- * Input: array 数组类地址
- * length 数组元素数量
- * Output:
- * Return:
- * Others:
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- void update(T* array, int length)
- {
- if( array != NULL )
- {
- T* temp = this->m_array; /* 此处不直接释放堆空间,防止此处抛出异常,保障动态数组异常安全性 */
-
- this->m_array = array; // 更新数组地址
- this->m_length = length; // 更新数组元素数量
-
- delete[] temp;
- }
- else
- {
- THROW_EXCEPTION(NoEnoughMemoryException, "No memory to update DynamicArray object ...");
- }
- }
-
- /**********************************************************************
- * Function: init()
- * Description: 初始化数组大小
- * Input: array 数组类地址
- * length 数组元素数量
- * Output:
- * Return:
- * Others:
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- void init(T* array, int length)
- {
- if( array != NULL )
- {
- this->m_array = array; // 初始化数组地址
- this->m_length = length; // 初始化数组元素数量
- }
- else
- {
- THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create DynamicArray object ...");
- }
- }
-
- public:
- /**********************************************************************
- * Function: DynamicArray()
- * Description: 构造函数 - 创建数组
- * Input: length 数组元素数量
- * Output:
- * Return:
- * Others:
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- DynamicArray(int length = 0)
- {
- init(new T[length], length);
- }
-
- /**********************************************************************
- * Function: DynamicArray()
- * Description: 拷贝构造函数
- * Input: obj 待拷贝的数组类
- * Output:
- * Return:
- * Others: 先创建拷贝数组类(copy),再初始化数组地址和数组元素数量(init)
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- DynamicArray(const DynamicArray<T>& obj)
- {
- init(copy(obj.m_array, obj.m_length, obj.m_length), obj.m_length);
- }
-
- /**********************************************************************
- * Function: operator=()
- * Description: 赋值构造函数
- * Input: obj 待拷贝的数组类
- * Output:
- * Return:
- * Others: 先创建拷贝数组类(copy),再更新数组地址和数组元素数量(update)
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- DynamicArray<T>& operator= (const DynamicArray<T>& obj)
- {
- if( this != &obj ) // 禁止自赋值
- {
- update(copy(obj.m_array, obj.m_length, obj.m_length), obj.m_length);
- }
-
- return *this;
- }
-
- /**********************************************************************
- * Function: length()
- * Description: 返回数组元素数量
- * Input:
- * Output:
- * Return: 返回数组元素数量
- * Others:
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- int length() const
- {
- return m_length;
- }
-
- /**********************************************************************
- * Function: resize()
- * Description: 重新分配数组的元素数量
- * Input: length 重新分配的数组元素数量
- * Output:
- * Return:
- * Others: 先创建拷贝数组类(copy),再更新数组地址和数组元素数量(update)
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- virtual void resize(int length)
- {
- if( length != m_length )
- {
- update(copy(this->m_array, m_length, length), length);
- }
- }
-
- /**********************************************************************
- * Function: ~DynamicArray()
- * Description: 析构函数
- * Input:
- * Output:
- * Return:
- * Others: 释放数组的堆空间
- * Modify Date Version Author Modification
- * ------------------------------------------------------------
- * 2022/03/10 1.0 Create
- **********************************************************************/
- ~DynamicArray()
- {
- delete[] this->m_array;
- }
- };
-
-
- }
-
- #endif // DYNAMICARRAY_H_