目录
【概念及类定义】
【概念】
顺序表即为线性表的顺序存储,线性表结点存放在存储器上一段连续的空间中,即一个数组。因为顺序表在进行插入操作时,需要额外的存储空间,所以在申请内存空间时,要留有余地。

【类定义】
template<class elemType> class seqList :public list<elemType>//模板list为线性表的抽象类模板 { private: elemType *data; int currentLength; int maxSize; void doubleSpace();//扩大数组容量 public: seqList(int initSize = 10);//构造函数,设置初始数组大小,代替create()的功能 ~seqList() { delete[]data; }//析构函数,将动态数组delete掉 void clear() { currentLength = 0; }//清空,没有必要把数组中的数都清空掉 //只需要将数组当前长度设置为0,虽然数组里面是有元素的 //但是逻辑上可以认为这些元素已经不属于这个顺序表了 int length()const { return currentLength; }//返回表长 void insert(int i, const elemType& x);//插入 void remove(int i);//删除 int search(const elemType& x)const;//搜索 elemType visit(int i)const { return data[i]; }//访问 void traverse()const;//遍历 };
上述代码中用到的 list 模板代码来自于这篇文章 【线性表的抽象类形式】
【容量不够的问题】
几乎所有顺序实现都会遇到一个问题,当添加数据的时候,该段内存空间已经被填满了,此时应该怎么办呢?
void doubleSpace();我们可以增加一个扩大数组容量的函数,我们把这个行为放在private中,不需要用户知道,给用户呈现出来的是,我们所建立的线性表是永远都不会存满的,所以要存在私有成员里。
我们利用这个函数把数组扩大为两倍长,但是不是申请一个空间接在原数组的后面,因为动态内存空间是在堆区申请的,第二次申请到的空间在哪里我们并不清楚,所以不能用拼接的方式来扩大数组。
那么我们可以直接申请一个长度为原数组两倍的一个动态数组,将原数组复制到新的数组中,这样就实现了扩大数组的功能。
【各个函数的具体实现】
//构造函数 template<class elemType> seqList<elemType>::seqList(int initSize) { data = new elemType[initSize];//创建一个动态数组 maxSize = initSize; currentLength = 0;//把这个表设置为空表 }//doubleSpace函数 template<class elemType> void seqList<elemType>::doubleSpace() { elemType* tmp = data;//把原来空间的起始地址保存起来 maxSize *= 2;//把最大长度扩大为原来的2倍 data = new elemType[maxSize];//再重新申请一个新的动态空间 for (int i = 0; i < currentLength; i++) data[i] = tmp[i];//把原来数组中内容拷贝过来 delete[]tmp;//清除原来申请的空间 }//insert函数 template<class elemType> void seqList<elemType>::insert(int i, const elemType& x) { if (currentLength == maxSize)//说明元素已经放满了,需要再开辟空间 doubleSpace(); for (int j = currentLength; j > i; j--) data[j] = data[j - 1]; data[i] = x; currentLength++; }//remove函数 template<class elemType> void seqList<elemType>::remove(int i) { for (int j = i; j < currentLength-1; j++) data[j] = data[j + 1]; currentLength--; }//search函数 template<class elemType> int seqList<elemType>::search(const elemType& x) const { for (int i = 0; i < currentLength && data[i] != x; i++);//注意此循环体为空,即只判断表达式 //所以循环退出的时候,只有两种情况:找到了x,没找到x且走到了表尾 if (i == currentLength) return -1; else return i; return 0; }//traverse函数 template<class elemType> void seqList<elemType>::traverse() const { cout << endl; for (int i = 0; i < currentLength; i++) cout << data[i] << ' '; }
【顺序表的优缺点】
(1)由于顺序表保持了逻辑次序和物理次序的一致性,使得定位访问的性能比较好;
(2)同时却因为要保持逻辑次序和物理次序的一致性,使得顺序表在执行增加和删除操作的时候会移动大量的数据;
(3)综合以上两点,顺序表比较适合做静态的,经常做线性访问的线性表。
本文详细介绍了顺序表的概念,通过C++模板类seqList展示了顺序表的实现,包括构造函数、插入、删除、搜索等操作。在容量不足时,通过`doubleSpace()`函数动态扩大数组容量。顺序表的优点在于其逻辑顺序与物理顺序一致,适合线性访问,但插入和删除操作可能涉及大量数据移动。

被折叠的 条评论
为什么被折叠?



