#ifndef SEQLIST_H
#define SEQLIST_H
#include "PerfCounter.h"
#include <cassert>
#include <cstdlib>
#include <iostream>
using namespace std;

#include "LinearList.h"
;
const int defaultSize = 100;

template <class T>
class SeqList : public LinearList<T>
{
protected:
    T *data;                  //存放数组
    int maxSize;              //最大可容纳表项数
    int last;                 //当前已存表项的最后位置（从0开始）
    void reSize(int newSize); //改变data数组空间大小
public:
    PerfCounter counter;
    SeqList(int sz = defaultSize); //构造函数
    SeqList(SeqList<T> &L);        //复制构造函数
    ~SeqList()
    {
        delete[] data;
    } //析构函数
    int Size() const
    { //计算表的最大可容纳表项个数
        return maxSize;
    }
    int Length() const
    { //计算表长度
        return last + 1;
    }
    int Search(T &x) const;         //搜索x在表中的位置，函数返回表项序号
    int Locate(int i) const;        //定位第i个表项，函数返回表项序号
    bool getData(int i, T &x) const //取第i个表项的值 放入x中
    {
        if (i > 0 && i <= last + 1)
        {
            x = data[i - 1];
            return true;
        }
        else
        {
            return false;
        }
    }
    void setData(int i, T &x) //用x修改第i个表项的值
    {
        if (i > 0 && i <= last + 1)
        {
            data[i - 1] = x;
        }
    }
    bool Insert(int i, T &x); //插入x在第i个表项后
    bool Remove(int i, T &x); //删除第i个表项，通过x返回表项的值
    bool IsEmpty() const      //判断表空否，空返回true，否则返回false
    {
        return (last == -1) ? true : false;
    }
    bool IsFull() const //判断表满否，满返回true，否则返回false
    {
        return (last == maxSize - 1) ? true : false;
    }
    void Sort();   //排序
    void input();  //输入
    void output(); //输出
    SeqList<T> *operator=(SeqList<T> &L)
    {
        T value;
        maxSize = L.Size();
        last = L.Length() - 1;
        //delete []data;//先清空
        data = new T[maxSize];
        if (data == NULL)
        {
            cerr << "Memory allocating error!" << endl;
            exit(1);
        }
        for (int i = 1; i <= last + 1; i++)
        {
            L.getData(i, value);
            data[i - 1] = value;
        }
        return this;
    }

    ///增加的函数成员：/////////////////////////////////////////////////////////////////////////////////////////////////////////
    void OrderInsert(T &item);                        //有序顺序表的有序插入
    void OrderMake(T *d, int len);                    //构造有序顺序表
    void MoreRemove(T &x);                            //删除有序顺序表值为x的重复元素
    void Merge(const SeqList &La, const SeqList &Lb); //归并有序表La和Lb
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
};

template <class T>
SeqList<T>::SeqList(int sz)
{
    if (sz > 0)
    {
        maxSize = sz;
        last = -1;
        data = new T[maxSize];
        if (data == NULL)
        {
            cerr << "Memory allocating error!" << endl;
            exit(1);
        }
    }
}

template <class T> //复制构造函数
SeqList<T>::SeqList(SeqList<T> &L)
{
    T value;
    maxSize = L.last();
    last = L.Length() - 1;
    data = new T[maxSize];
    if (data == NULL)
    {
        cerr << "Memory allocating error!" << endl;
        exit(1);
    }
    for (int i = 1; i <= last + 1; i++)
    {
        L.getData(i, value);
        data[i - 1] = value;
    }
}

template <class T> //扩容至元素个数为newSize个
void SeqList<T>::reSize(int newSize)
{
    if (newSize <= 0)
    {
        cerr << "Invalid array index!" << endl;
        return;
    }
    if (newSize != maxSize)
    {
        T *newarray = new T[newSize];
        if (newarray == NULL)
        {
            cerr << "Memory allocating error!" << endl;
            exit(1);
        }
        int n = last + 1;
        T *srcptr = data;
        T *destptr = newarray;
        while (n--)
            *destptr++ = *srcptr++;
        delete[] data;
        data = newarray;
        maxSize = newSize;
    }
}

template <class T> //查找第一个值为x的元素下标
int SeqList<T>::Search(T &x) const
{
    for (int i = 0; i <= last; i++)
    {
        if (data[i] == x)
            return i + 1;
    }
    return 0;
}

template <class T> //定位第i个元素的位置
int SeqList<T>::Locate(int i) const
{
    if (i >= 1 && i <= last + 1)
        return i;
    else
        return 0;
}

template <class T> //在第i个元素后插x
bool SeqList<T>::Insert(int i, T &x)
{
    if (last == maxSize - 1)
        return false;
    if (i < 0 || i > last + 1)
        return false;
    for (int j = last; j >= i; j--)
        data[j + 1] = data[j];
    data[i] = x;
    last++;
    return true;
}

template <class T> //删除第i个元素并通过x返回
bool SeqList<T>::Remove(int i, T &x)
{
    if (last == -1)
        return false;
    if (i < 1 || i > last + 1)
        return false;
    x = data[i - 1];
    for (int j = i; j <= last; j++)
        data[j - 1] = data[j];
    last--;
    return true;
}

template <class T>
void SeqList<T>::Sort()
{ //冒泡排序:从小到大排序
    for (int i = 1; i <= last; i++)
    {
        for (int j = last; j >= i; j--)
        {
            if (data[j - 1] > data[j])
            {
                T tmp = data[j - 1];
                data[j - 1] = data[j];
                data[j] = tmp;
            }
        }
    }
}

template <class T> //从键盘逐个输入数据并建立顺序表
void SeqList<T>::input()
{
    cout << "开始建立顺序表，请输入表中元素个数：Input the size of the list which will be created:";
    while (1)
    {
        assert(cin >> last);
        last--;
        if (last < 0)
        {
            cout << "Input error, the last must be positive!\n";
            cout << "Input the last again:";
        }
        else if (last > maxSize - 1)
        {
            cout << "Input error, the last must be less than maxSize!\n";
            cout << "Input the last again:";
        }
        else
            break;
    }
    cout << "\nInput the data for each element to create the list:" << endl;
    for (int i = 0; i <= last; i++)
    {
        cout << "#" << i + 1 << ":";
        assert(cin >> data[i]);
    }
}

template <class T> //将顺序表输出到屏幕
void SeqList<T>::output()
{
    cout << "\nThe size of the list is:" << last + 1 << endl;
    for (int i = 0; i <= last; i++)
        cout << "#" << i + 1 << ":\t" << data[i] << endl;
}

/**
 * OrderInsert()在有序顺序表L中的合适位置插入数据元素x，使得L中的数据元素按值非递减有序排列。
 **/
template <class T>
void SeqList<T>::OrderInsert(T &item)
{
    //在这里加入实现第一个任务的程序。
    int pos = 0;
    for (; pos <= last; pos++)
    {
        counter.inc_cmp(1);
        if (data[pos] >= item)
            break;
    }
    for (int j = last; j >= pos; j--)
        data[j + 1] = data[j], counter.inc_mov(1);
    data[pos] = item, counter.inc_mov(1);
    last++;
}

/**
 * MoreRemove()在有序顺序表L中删除所有值为x的元素。
 **/
template <class T>
void SeqList<T>::MoreRemove(T &x)
{
    //在这里加入实现第三个任务的程序。
    //有序顺序表中可能有重复的x值，删除有序顺序表中重复的x值.
    //要求算法尽可能高效——尽可能减少移动元素的次数。
    //在你的readme.txt文件中描述算法，并分析算法的时间复杂度和空间复杂度。
    counter.inc_mem(8);
    int pos1 = -1, pos2 = -1;
    for (int i = 0; i <= last; i++)
    {
        counter.inc_cmp(1);
        if (data[i] == x)
        {
            pos2 = pos1 = i;
            while (data[pos2] == x) counter.inc_cmp(1), pos2++;
            break;
        }
    }
    if (pos1 == -1) return;
    int dif = pos2 - pos1;
    int newLast = last - dif;
    for (int i = pos1; i <= newLast; i++)
        data[i] = data[i + dif], counter.inc_mov(1);
    last = newLast, counter.inc_mov(1);
}

/**
 * OrderMake()从数组d依次取len个数据元素有序插入到有序顺序表L中。
 **/
template <class T>
void SeqList<T>::OrderMake(T *d, int len)
{
    for (int i = 0; i < len; i++)
        OrderInsert(d[i]);
}

//有序表的合并。认真学习该算法。
template <class T>
void SeqList<T>::Merge(const SeqList &La, const SeqList &Lb)
{
    int i, j;
    T xa, xb;
    last = -1;
    i = 1;
    j = 1;
    while (i <= La.Length() && j <= Lb.Length()) /*两个表中都有元素未比完*/
    {
        if (last == maxSize - 1)
            reSize(2 * maxSize);
        La.getData(i, xa);
        Lb.getData(j, xb);
        if (xa <= xb)
        {
            Insert(last + 1, xa);
            i++;
        }
        else
        {
            Insert(last + 1, xb);
            j++;
        }
    }
    while (i <= La.Length()) /*Lb表的元素已经比完*/
    {
        if (last == maxSize - 1) reSize(2 * maxSize);
        La.getData(i, xa);
        Insert(last + 1, xa);
        i++;
    }
    while (j <= Lb.Length()) /*La表的元素已经比完*/
    {
        if (last == maxSize - 1) reSize(2 * maxSize);
        Lb.getData(j, xb);
        Insert(last + 1, xb);
        j++;
    }
}
#endif