一.线性表的定义
线性表是一个若干个数据元素组成的有限序列
作为“序列”,除了第一个和最后一个元素,都是有前驱和后继的
二.顺序表的实现
顺序表是线性表的顺序存储方式,需要用到一段地址连续的存储单元来存储数据
顺序存储结构需要三个属性:
-
存储空间的起始位置: 数组data
-
线性表的最大存储空间:maxSize
-
线性表的当前长度:last
我们重点来聊一聊数组长度和线性表长度的区别
-
数组长度maxSize是存放线性表存储空间的长度,一般是不变的,但是也可以改,但是会有损耗
-
线性表长度last是存放的数据元素的个数,这个是可以随意改变的
-
last≤maxSize
那么顺序表类中的private部分的定义如下
template <class T>
class SeqList{
private:
T *data;
int maxSize;
int last;
//这里也可以添加修改数组长度的函数,看个人需求
}
三.地址计算方法
Loc(第i个元素)=Loc(第一个元素)+(i-1)* c
c表示一个数据元素所占的存储空间
时间复杂程度为O(1)
通常把这种存储结构称为随机存储结构
四.顺序表的插入与删除操作
1.获取元素的操作
template <class T>
bool getData(int i,T&x){
if(i>=0&&i<=last){ //判断i是否合法
x=data[i];
return true;
}else{
return false;
}
}
2.插入操作
算法思路如下:
-
如果线性表长度≥数组长度,抛出异常
-
如果插入位置不合理,抛出异常
-
从最后一个元素开始向前遍历到第i个位置,分别向后移动一个位置
-
将要插入的元素添入位置中
-
表长+1
那我们就来动手操作
template <class T>
bool Insert(int i,T&x){
//第一步操作
if(last>=maxSize-1){
return false;
}
//第二步操作
if(i<0||i>last){
return false;
}
//第三步操作
for(int j=last;j>=i;j--){
data[j+1]=data[j]; //后移操作
}
//第四步操作
data[i]=x;
//第五步操作
last++;
return true;
}
每一个数据结构我们需要熟练掌握其增删改减的方法,非常重要
3.删除操作
基本算法如下:
-
删除的位置不合理,抛出异常(记得判断是否表空)
-
取出删除元素
-
从删除元素的位置开始遍历到最后一个元素,将它们向前移动一个位置
-
表长减1
template <class T>
bool Delete(int i,T&x){
//第一步
if(last==0){
return false;
}
if(i<0||i>last){
return false;
}
//第二步
x=data[i];
//第三步
for(int j=i;j<last;j++){
data[j]=data[j+1];
}
//第四步
last--;
return true;
}
用之前学到的大O()推导式我们可以得出
插入和删除的时间复杂程度是O(n)
详细内容见:数据结构中的基础算法-CSDN博客
五.顺序表的优缺点
优点:
-
无需增加额外的存储空间
-
可以快速存取任一位置的元素
缺点:
-
插入和删除需要移动大量元素
-
线性表长度变化大时,难以确定存储空间的容量
-
造成存储空间的“碎片”
六.顺序表类的完整代码
本人一直用的代码,大家可以参考着写
#include <iostream>
using namespace std;
const int defaultSize = 100;
template<class T>
class SeqList {
protected:
T* data;
int maxSize;
int last;//从零开始存的最后一个位置
void reSize(int newSize);
public:
SeqList(int sz = defaultSize);
SeqList(SeqList<T>& L);
~SeqList() { delete[] data; }
int Size()const { return maxSize; }
int Length() { return last + 1; }
int Search(T& x)const; //const保护对象数据成员,且const成员函数执行时不能调用非const成员函数
int Locate(int i)const;
bool getData(int i, T& x)const
{//输入的是第i位元素0,1,2,3...
if (i >= 0 && i <= last) { x = data[i]; return true; }
else return false;
}
void setData(int i, T& x)
{//与上面同样 修改后:
if (i >= 0 && i <= last)data[i] = x;
}
bool Insert(int i, T& x);
bool Remove(int i, T& x);
bool IsEmpty() { return (last == -1) ? true : false; }
bool IsFull() { return (last == maxSize - 1) ? true : false; }
void input();
void output();
SeqList<T>operator=(SeqList<T>& L);
};
template <class T>
SeqList<T>::SeqList(int sz) {
if (sz > 0) {
maxSize = sz;
last = maxSize - 1;//修改01
data = new T[maxSize];
//if (data == NULL)
//{
// cerr << "存储分配错误!" << endl; exit(1);
//}
}
}
template <class T>
SeqList<T>::SeqList(SeqList<T>& L) {
maxSize = L.Size();
last = L.Length() - 1;
T value;
data = new T[maxSize];
// if (data == NULL)
// {
// cerr << "存储分配错误!" << endl; exit(1);
//}
for (int i = 0; i <= last; i++) {
L.getData(i, value);
data[i] = value;
}
}
template <class T>
void SeqList<T>::reSize(int newSize) {//未测试
if (newSize <= 0)
{
cout << "无效的数组大小" << endl;
}
if (newSize != maxSize) {
T* newarray = new T[newSize];
// if (newarray == NULL)
// {
// cerr << "存储分配错误!" << 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>
int SeqList<T>::Search(T& x)const {
for (int i = 0; i <= last; i++)//修改
if (data[i] == x)
return i;
return 0;
}
template<class T>
int SeqList<T>::Locate(int i) const {
if (i >= 0 && i <= last)//修改 ...这函数有什么用?
return i;
else
return 0;
}
template <class T>
bool SeqList<T>::Insert(int i, T& x) {//第i位
if (last == maxSize - 1)
return false;
if (i<0 || i>last)
return false;
for (int j = last; j >= i; j--)
data[j + 1] = data[j];
data[i] = x;
last++;
return true;
}
template <class T>
bool SeqList<T>::Remove(int i, T& x) {
if (last == -1)
return false;
if (i<0 || i>last)return false;
x = data[i];//存被删除的元素的值
for (int j = i; j < last; j++)
data[j] = data[j + 1];//修改03
last--;
return true;
}
template <class T>
void SeqList<T>::input() {
// cout << "开始建立顺序表,请输入表中元素个数:";
while (1) {
cin >> last;
last -= 1;//修改02
if (last <= maxSize)
break;
//cout << "表中元素个数输入有误,范围不能超过" << maxSize - 1 << ":";
}
for (int i = 0; i <= last; i++) {
// cout << i << " ";
cin >> data[i];
}
}
template <class T>
void SeqList<T>::output() {
//cout << "顺序表当前元素最后位置:" << last << endl;
cout<<"{"<<" ";
for (int i = 0; i <= last; i++)
cout << data[i] << " ";
cout <<"}"<< endl;
}
template <class T>
SeqList<T> SeqList<T>::operator = (SeqList<T>& L) {
delete data;
maxSize = L.Size();
last = L.Length() - 1;
T value;
data = new T[maxSize];
//if (data == NULL)
//{
// cerr << "存储分配错误!" << endl; exit(1);
// }
for (int i = 0; i <= last; i++) {//修改04
L.getData(i, value);
data[i] = value;
}
return *this;
}