顺序表的实现_数组


#include 
using namespace std;

#define InitSize 10 //动态数组的初始化尺寸
#define IncSize 5   //当动态数组存满数据后每次扩容的元素个数

/*
//静态数组来保存顺序表中的元素
typedef struct
{
    int m_data[10];//10个位置
    int m_length;//顺序表中当前实际长度,当前顺序表中存储的元素个数
}SeqList01;

//动态数组来保存顺序表中的元素
typedef struct
{
    int *m_pData;//顺序表中的元素保存在m_pData指向的内存空间中
    int m_length;//顺序表中存储元素的实际长度
    int m_maxSize;//动态数组的最大容量,动态数组可以扩容,记录该值
}SeqList02;

*/

template //T表示数组中的元素类型
class SeqList
{
    public:
        SeqList(int length=InitSize);//构造函数,参数可以有默认值
        ~SeqList();//析构函数
    
        
    public:
        bool ListInsert(int i, const T&e);//在第i个位置插入指定元素e
        bool ListDelete(int i);//删除第i个位置的元素
        bool GetElement(int i, T&e);//获取第i个元素的值
        int LocateElement(const T&e);//按照元素值查找其在顺序表中出现的位置

        void DisaplayList();//输出线性表中的所有数据
        int GetListLength();//获取线性表的长度
        void ReverseList();//翻转线性表
        void TraverseList();//遍历数组中的元素,并输出

    private:
        void IncreaseSize();//当顺序表存储数据满,调用次函数为书虚表扩容。
    private:
            T *m_pData;//顺序表中的元素保存在m_pData指向的内存空间中
            int m_length;//顺序表中存储元素的实际长度
            int m_maxSize;//动态数组的最大容量,动态数组可以扩容,记录该值

};

//在外面进行函数的定义
template
SeqList::SeqList(int length)
{
    m_pData = new T[length];//为一维数组动态分配内存
    m_length = 0;            //顺序表当前长度为0,表示还没存入任何数据元素
    m_maxSize = length;        //当前最多可以存入的数据的个数m_maxSize
}

//通过析构函数来对线性表进行资源释放
template
SeqList::~SeqList()
{
    delete[]m_pData;
    //将数组中的元素个数归为0;
    m_length = 0;
}

/*
在第i个位置后面插入元素e,时间复杂度为O(n),时间开销主要源于元素的移动。
如插入位置为3的位置,则3后面的元素都需要移动。
注意:数组的下标从0开始,位置从1开始编号。所以下标和位置的对应关系是 
位置-1==数组编号
*/
template
bool SeqList::ListInsert(int i, const T&e)
{
    //如果顺序表的元素已经满,那么插入数据失败
    if (m_length >= m_maxSize)
    {
        //cout << "顺序表中的元素已经满了,插入失败" << endl;
        //return false;

        //扩容
        IncreaseSize();
    }

    //判断插入数据的位置i是否合法,i的合法值应该从1到m_length+1之间
    if ((i < 1) || (i > (m_length + 1)))
    {
        cout << "插入数据的位置不合法,请重新检查插入位置" << m_length + 1 << endl;
        return false;
    }

    /*
    从最后一个元素向前面遍历,到插入新元素的第i个位置,分别将这些位置中元素向后移动。
    如向位置为2的位置插入一个元素,那么就是插入到数组中编号为1的位置,
    向位置为i的位置插入一个元素,那么就是插入到数组中编号为i-1的位置,
    
    如数组长度为5,向第2个位置插入数据,则需要将数组标号为1的元素向后依次移动。

    分析时间复杂度为(1+2+3+4+....(n-1)+n)/(n+1)= n/2

    */
    for (int j = m_length; j >= i; j--)
    {
        m_pData[j] = m_pData[j-1];
    }
    //在位置为i的位置插入元素,因为数组下标从0开始,所以存储在数组中的位置是i-1
    m_pData[i-1] = e;
    cout << "成功在位置为i==" << i << "的位置插入元素" << e << endl;

    //将数组中的存储元素的个数增加1
    m_length++;
    cout << "当前数组中元素的个数"< endl;
       
    return true;
}


/*
 删除第i个位置的元素,则后面的元素需要一次前移动

*/
template
bool SeqList::ListDelete(int i)
{
    //判断线性表是否为空,如果元素的个数为空,则提示不能删除
    if (m_length < 1)
    {
        cout << "线性表为空,删除失败" << endl;
        return false;
    }

    //判断删除元素的位置是否合法,i<1或者i>m_length,则不合法
    if ((i < 1) || (i > m_length))
    {
        cout << "删除的位置" << i << "不合法" << "删除的元素应该在" << i << "" << m_length << "之间" << endl;        
        return false;
    }

    cout << "删除元素i==" << i << "位置元素" << m_pData[i - 1] << "成功" << endl;
    //执行删除元素的代码,删除i位置,则存储在数组中是i-1,则后面的元素都需要向前面移动
    for (int j = i; j < m_length; j++)
    {
        m_pData[j - 1] = m_pData[j];
            
    }
    //拷贝完毕,最后一个位置的元素应该删除,否则最后一个元素数值不为0
    m_pData[m_length - 1] = 0;
    m_length--;
    //注意这里的元素已经删除,输出的是删除元素之后的下一个元素
    //cout << "删除元素i==" << i << "位置元素" << m_pData[i - 1] << "成功" << endl;
    cout << "删除元素i==" << i << "位置元素成功" << endl;
    return true;

}

//获取第i个位置的元素值,并使用e返回
template
bool SeqList::GetElement(int i, T & e)
{
    //判断数组的长度
    if (m_length < 1)
    {
        cout << "线性表的长度为0,不能获取元素" << endl;
        return false;
    }

    //判断获取的位置是否合法
    if ((i < 1) || i > m_length)
    {
        cout << "获取的位置不合法" << endl;
        return false;
    }
    e = m_pData[i - 1];//第i个位置保存在数组中位置为i-1
    cout << "成功获取位置为i==" << i <<"的元素"<< endl;

    return true;
}

//按照元素值查找其在顺序表中出现的位置
template
int SeqList::LocateElement(const T&e)
{
    for (int k = 0; k < m_length; k++)
    {
        if (e == m_pData[k])
        {
            //e = m_pData[k];
            cout << "线性表中存在元素值为" << e << "的元素" << endl;
            return k+1;//k为数组中的存储位置,返回值应该加1,表示是第几个元素
        }        
    }
    cout << "线性表中不存在元素值为" << e << "的元素" << endl;

    return 0;

}

//遍历输出
template
void SeqList::DisaplayList()
{
    TraverseList();
}

//获取线性表的长度
template
int SeqList::GetListLength()
{
    return m_length;
}

//反转线性表,
template
void SeqList::ReverseList()
{
    //翻转数组中的元素 编号为i的位置和编号为数组总编号-i的位置进行交换(m_length-1数组最高的位置的编号)
    T tep;
    for (int i = 0; i < m_length/2; i++)//这里如果没有 /2,会交换两次==等价于没交换
    {
        tep = m_pData[i];
        m_pData[i] = m_pData[m_length - 1 - i];
        m_pData[m_length - 1 - i] = tep;
    }

}

//数组元素的遍历输出
template
void SeqList::TraverseList()
{
    for (int k = 0; k < m_length; k++)
    {
        cout << m_pData[k] << endl;
    }
}

template
void SeqList::IncreaseSize()
{
    T *p = m_pData;
    m_pData = new T[m_maxSize + IncSize];//重新为线性表分配更大的内存空间
    for (int i = 0; i < m_length; i++)
    {
        //把数据搬移过去
        m_pData[i] = p[i];
    }
    //设置最大存储数据的数量
    m_maxSize = m_maxSize + IncSize;
    //释放原来的内存空间
    delete[]p;


}

int main()
{

    SeqList<int>* seqList = new SeqList<int>(10);
    //注意插入空线性表只能从第一个位置开始插入,否则会报错
    seqList->ListInsert(1, 1111);
    seqList->ListInsert(2, 2222);
    seqList->ListInsert(3, 3333);
    seqList->ListInsert(4, 4444);

    seqList->TraverseList();

    seqList->ListDelete(2);
    seqList->TraverseList();

    //测试获取元素的位置
    int value = 0;
    seqList->GetElement(3, value);
    cout << "value=="< endl;

    //查找线性表中是否包含e元素,并将值返回
    int number01= seqList->LocateElement(3333);
    cout << "number01==" << number01 << endl;


    //翻转数组
    cout << "-----------------------------" << endl;
    seqList->TraverseList();
    cout << "*****************************" << endl;
    seqList->ReverseList();
    seqList->TraverseList();



    cout << "扩容*****************************" << endl;
    //测试扩容函数
    for (int i = 1; i < 30; i++)
    {
        seqList->ListInsert(i, i * 3);
        
    }
    seqList->TraverseList();


    std::cout << "Hello World!\n";
    return 0;
}
/*
2021年11月8日21点28分

*/