顺序表

顺序表是线性表除了链表的另外一种形式,底层是以数组实现,功能类似于STL中的vector

顺序表支持随机查找,查找的时间复杂度是O(1),但是由于删除和插入操作都要涉及到数据的整体移动,因此删除和插入操作的平均时间复杂度也是O(n)级别的,对于需要频繁查找的情景顺序表更好用,对于需要频繁插入删除的情景链表更好用。

链表的插入还需要考虑扩容的问题,当链表容量不足以放下下一个数据时,就需要申请一个两倍大小的新顺序表然后把数据整体搬迁到新顺序表中,这个工作也是O(n)复杂度。

最后有一个小技巧,即顺序表的清空clear()函数不需要真的把表中每个元素修改成0,只需要修改当前表长即可,当先表长会限制操作的范围,每一次插入其实都只是在修改原来在这个位置上的值而已。

#include <iostream>
using namespace std;

// 线性表:顺序表和链表共同的抽象类
template<typename elemType>
class list{
public:
    virtual void clear() = 0;                            // 删除线性表中的所有数据元素
    virtual int length() const = 0;                      // 求线性表的长度
    virtual void insert(int i, const elemType & x) = 0;  // 在第i个位置插入一个元素
    virtual void remove(int i) = 0;                       // 删除第i个位置的元素
    virtual int search(const elemType & x) const = 0;          // 搜索某个元素x在线性表中是否出现
    virtual elemType visit(int i) const = 0;             // 返回线性表中第i个数据元素的值
    virtual void traverse() const = 0;                   // 按序访问线性表的每一数据元素
    virtual ~list(){};
};


// 顺序表
template<typename elemType>
class seqList:public list<elemType>{
private:
    elemType* data;
    int currentLength;
    int maxSize;
    void doubleSpace();

    class OutOfBoundError{};
    class InitalSizeError{};
public:
    seqList(int initSize = 10);
    ~seqList();
    void clear();
    int length() const;
    void insert(int i, const elemType & x);
    void remove(int i);
    int search(const elemType & x) const;
    elemType visit(int i) const;
    void traverse() const;
};


template<typename elemType>
seqList<elemType>::seqList(int initSize){
    if(initSize <= 0) throw InitalSizeError();

    data = new elemType[initSize];
    maxSize = initSize;
    currentLength = 0;
}


template<typename elemType>
seqList<elemType>::~seqList(){
    delete []data;
}


template<typename elemType>
void seqList<elemType>::clear(){
    currentLength = 0;
}


template<typename elemType>
int seqList<elemType>::length() const{
    return currentLength;
}


template<typename elemType>
elemType seqList<elemType>::visit(int i) const{
    if(i < 0 || i >= currentLength) throw OutOfBoundError();

    return data[i];
}


template<typename elemType>
void seqList<elemType>::traverse() const{
    for(int i = 0; i < currentLength; ++i)
        cout << data[i] << ' ';
    cout << endl;
}


template<typename elemType>
int seqList<elemType>::search(const elemType & x) const{
    int i = 0;
    for(; i < currentLength && data[i] != x; ++i);
    if(i == currentLength) return -1; else return i;
}


template<typename elemType>
void seqList<elemType>::doubleSpace(){
    elemType* tmp = data;
    maxSize *= 2;
    data = new elemType[maxSize];
    for(int i = 0; i < currentLength; ++i)
        data[i] = tmp[i];
    delete []tmp;
}


template<typename elemType>
void seqList<elemType>::insert(int i, const elemType & x){
    if(i < 0 || i > currentLength) throw OutOfBoundError();

    if (currentLength == maxSize) doubleSpace();
    for(int j = currentLength; j > i; j--)
        data[j] = data[j - 1];
    data[i] = x;
    ++currentLength;
}


template<typename elemType>
void seqList<elemType>::remove(int i){
    if(i < 0 || i >= currentLength) throw OutOfBoundError();

    for(int j = i; j < currentLength - 1; j++)
        data[j] = data[j + 1];
    --currentLength;
}

 

上一篇:数据结构——进制转换(10—n)


下一篇:Clion中使用头文件和源文件坑