想知道什么是顺序表,你就要先知道什么是线性表,线性表是N个具有相同特性的数据元素的有序序列,而线性表的顺序存储就是顺序表
如果你听不懂,完全没有关系,因为我作为一个已经学完了顺序表的人,我也看不懂
那我们应该如何去理解它呢?我们其实在不知道这个概念的时候已经在大量的使用它了,没错,数组就是顺序表
我们实现顺序表其实分为两种形式,一种是动态,一种是静态,它们是什么意思呢?
动态的就是它会根据你输入数据的多少来扩充数组的大小,这种方式可以节省空间开销,但是一次又一次的扩容会使你的时间开销变大
而静态就是一劳永逸的创建一个数组,使它的空间足够大,以避免出现二次扩容的情况,那你也很容易想到这种方式可以节省时间开销,但会使空间开销变大
我们今天主要来介绍静态的实现方式,这也是竞赛中用到最多的形式
1.创建顺序表
cpp
const int N = 100;
int a[N], n; //n用来记录有多少元素
大家可以看到,其实创建一个顺序表非常简单,只是一个数组而已,因为我目前的编辑版本是支持用 const 定义的整形去充当数组的长度的
2.插入元素
2.1尾插
cpp
void push_back(int x) //尾插
{
a[n] = x;
n++;
}
在这里你可以尝试另一种写法,也就是先 ++n 再插入元素,这样就可以把下标为0的位置空出来,这样有利于你后面去执行各种各样的操作
2.2 头插
cpp
void push_front(int x) //头插
{
int temp = n - 1;
for(int i = temp; i >= 0; i--)
{
a[i + 1] = a[i];
}
a[0] = x;
n++;
}
**要执行头插操作,就要把之前的所有元素全部向后移一位,然后在最开始的地方插入元素,**那你就很好理解为什么我会这么写了,我就是把每一个元素的值赋给它的下一位,然后在下标为0的位置插入元素
2.3 在任意位置插入
cpp
void push_p(int x, int p)
{
for(int i = n; i >= p; i--)
{
a[i + 1] = a[i];
}
a[p] = x;
n++;
}
这个代码的逻辑就是把 p 后面所有元素向后移位,然后在 p 这个位置插入元素,如果你想在测试程序的时候感受一下绝望的话,这里千万不要记起 n++
2.4 程序测试
cpp
const int N = 100;
int a[N], n; //n用来记录有多少元素
void push_back(int x) //尾插
{
a[n] = x;
n++;
}
void push_front(int x) //头插
{
int temp = n - 1;
for(int i = temp; i >= 0; i--)
{
a[i + 1] = a[i];
}
a[0] = x;
n++;
}
//在任意位置插入
void push_p(int x, int p)
{
for(int i = n; i >= p; i--)
{
a[i + 1] = a[i];
}
a[p] = x;
n++;
}
void print(int n)
{
for(int i = 0; i < n; i++)
{
cout << a[i] << ' ';
}
cout << endl << endl;
}
int main()
{
cout << "尾插" << endl;
push_back(1); //在数组尾部插入元素
print(n);
push_back(4);
print(n);
push_back(6);
print(n);
push_back(9);
print(n);
cout << "头插" << endl;
push_front(2); //在数组尾部插入元素
print(n);
push_front(3);
print(n);
//在任意位置插入元素
cout << "在任意位置插入" << endl;
push_p(5,2);
print(n);
return 0;
}
完成了插入操作后可以进行测试,大家可以试着自己写一下这段代码,我的代码是没错的,如果你写代码出了问题,可以作为对照
3.删除元素
3.1头删
cpp
void pop_front() //头删
{
--n;
for(int i = 0; i < n; i++)
{
a[i] = a[i + 1];
}
}
这段代码的逻辑是使每一个数被后一个数所赋值,第一个元素就自然被删除了
3.2 尾删
cpp
void pop_back() //尾删
{
--n;
}
3.3 在任意位置删除
cpp
void pop_p(int p) //在任意位置删除
{
--n;
for(int i = n; i > p; i--)
{
a[i - 1] = a[i];
}
}
这其实和头删的逻辑很相似,就是把 p 之后的元素被后一个元素覆盖
3.4程序测试
cpp
const int N = 100;
int a[N], n; //n用来记录有多少元素
void push_back(int x) //尾插
{
a[n] = x;
n++;
}
void push_front(int x) //头插
{
int temp = n - 1;
for(int i = temp; i >= 0; i--)
{
a[i + 1] = a[i];
}
a[0] = x;
n++;
}
//在任意位置插入
void push_p(int x, int p)
{
for(int i = n; i >= p; i--)
{
a[i + 1] = a[i];
}
a[p] = x;
n++;
}
void pop_front() //头删
{
--n;
for(int i = 0; i < n; i++)
{
a[i] = a[i + 1];
}
}
void pop_back() //尾删
{
--n;
}
void pop_p(int p) //在任意位置删除
{
--n;
for(int i = n; i > p; i--)
{
a[i - 1] = a[i];
}
}
void print(int n)
{
for(int i = 0; i < n; i++)
{
cout << a[i] << ' ';
}
cout << endl << endl;
}
int main()
{
cout << "尾插" << endl;
push_back(1); //在数组尾部插入元素
print(n);
push_back(4);
print(n);
push_back(6);
print(n);
push_back(9);
print(n);
cout << "头插" << endl;
push_front(2); //在数组尾部插入元素
print(n);
push_front(3);
print(n);
//在任意位置插入元素
cout << "在任意位置插入" << endl;
push_p(5,2);
print(n);
cout << "头删" << endl;
pop_front(); //在头部删除一个元素
print(n);
cout << "尾删" << endl;
pop_back(); //在尾部删除一个元素
print(n);
cout << "在任意位置删除" << endl;
pop_p(3);
print(n);
return 0;
}
4.查找
4.1 按值查找
cpp
int find(int x) //按值查找
{
for(int i = 0; i < n; i++)
{
if(a[i] == x)
{
return i;
}
}
return 0;
}
4.2 按位查找
cpp
int at(int p) //按位查找
{
return a[p];
}
4.3 按位修改
cpp
void change(int p, int x) //按位修改
{
a[p] = x;
}