知识点:
顺序表也就是线性表的顺序表示,线性表的顺序表示指的是用一组连续的存储单元一次存储线性表的数据元素。
也就是说顺序表的逻辑关系与物理关系是一致的,各项数据元素在逻辑上相邻,在物理存储上也相邻。
由于顺序表的这种特性如果我们假设第一个元素的存储地址是LOC(a1),每个数据元素占用l个存储单元,那么我们可以知道:
LOC(ai)= LOC(a1)+(i - 1)* l。
如果我们知道我们想要访问的是循序表当中的第几个元素我们就可以通过基地址加上偏移量来直接访问我们想要访问的数据元素,因此我们说顺序表是随机存储。
在顺序表当中存在两个域,一个是指针域用来指向基地址,另一个就是表示顺序表当前长度的域是一个整型的变量。
练习题:
判断:
1-1对于顺序存储的长度为N的线性表,访问结点和增加结点的时间复杂度分别对应为O(1)和O(N)。(T) (1分)
解析:访问某个结点我们只需要计算偏移量即可,实际上就是通过数组下标来访问。但是增加结点,必须将部分结点后移,将插入位置空出来才能进行插入,那么考虑最坏的情况就是在第1个结点之前插入结点,因此移动n次,时间复杂度就是O(n)。
1-2若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用顺序表存储最节省时间。(T)
解析:在1-1当中我们知道了,删除顺序表当中的结点与增加顺序表当中的结点都是要对部分结点进行移动的,但是,如果仅仅是在最后一个节点后面插入新的结点或者是删除最后一个结点,我们是可以用O(1)的时间完成的,因为顺序表示随机存取的,我们计算偏移量之后,就可以知道最后一个结点的位置,因此我们就可以进行删除与增加,同时改变length的大小即可,那么存取操作更不用说了。
1-3对于顺序存储的长度为N的线性表,删除第一个元素和插入最后一个元素的时间复杂度分别对应为O(1)和O(N)。 (F)(1分)
解析:从前面我们知道,顺序表删除第一个元素,后面的元素全部要往前移动,移动n-1次,因此是O(n),但是在最后插入元素我么从1-2知道是O(1)的。
1-4在顺序表中逻辑上相邻的元素,其对应的物理位置也是相邻的。 (T)(1分)
解析:因为顺序表在逻辑上是相邻的,在物理位置上也是相邻的,因此我们才将这样的线性表,成为顺序表。
1-5所谓随机存取,就是通过首地址和元素的位序号值可以在O(1)的时间内找到指定的元素。 (T)(1分)
解析:自己理解一下吧,顺序存取就是通过基地址加上偏移量,然后可以直接访问第i个数据元素。
1-6顺序存储的线性表不支持随机存取。 (F)(1分)
解析:我们知道顺序表示随机存取的。
1-7在顺序表上进行插入、删除操作时需要移动元素的个数与待插入或待删除元素的位置无关。(F)
解析:顺序表的插入与删除都需要进行结点的移动,但是,最后一个结点的删除与在最后一个结点后面插入元素不需要移动,因此移动元素的个数与插入或待删除元素的位置是有关系的。
选择题:
2-1对于顺序存储的长度为N的线性表,访问结点和增加结点的时间复杂度为:(1分)
- O(1), O(1)
- O(1), O(N)
- O(N), O(1)
- O(N), O(N)
解析:因为顺序表示随机存取,因此访问结点是O(1),而增加结点涉及到结点的移动,因此是O(n)。
2-2在N个结点的顺序表中,算法的时间复杂度为O(1)的操作是:(2分)
- 访问第i个结点(1≤i≤N)和求第i个结点的直接前驱(2≤i≤N)
- 在第i个结点后插入一个新结点(1≤i≤N)
- 删除第i个结点(1≤i≤N)
- 将N个结点从小到大排序
解析:对于顺序表的随机存储我们可以知道第一个是对的。而第二个第三个涉及到移动是O(n)的。排序算法没有O(1)的。
2-3若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用哪种存储方式最节省时间? (2分)
- 双链表
- 单循环链表
- 带头结点的双循环链表
- 顺序表
解析:审题很重要,题目给出的操作是存取指定序号的元素和在最后进行操作,这些都符合顺序表的特性。
2-4顺序表中第一个元素的存储地址是100,每个元素的长度为2,则第5个元素的地址是( )。(2分)
- 100
- 105
- 108
- 110
解析:根据基地址加上偏移量,也就是前面的公式,我们知道第三个是对的。
2-5线性表的顺序存储结构是一种( ) (2分)
- 随机存取的存储结构
- 顺序存取的存储结构
- 索引存取的存储结构
- 散列存取的存储结构
解析:这个已经记住了吧,是随机存取。
2-6个顺序表所占用的存储空间大小与( )无关。 (2分)
- 表的长度
- 元素的类型
- 元素的存放顺序
- 元素中各字段的类型
解析:顺序表的结点包括两个域,其中指针域指向的是基地址,但是所占的存储空间,与数据元素的类型有关。
2-7要将一个顺序表{a0,a1,……,an−1}中第i个数据元素ai(0≤i≤n-1)删除,需要移动( )个数据元素。 (2分)
- i
- n-i-1
- n-i
- n-i+1
解析:删除元素,移动的次数是ai后面的所有元素,因此应该是n-(i+1)。
注:这里的i是下标,并不是数组元素的序号。
2-8用数组表示线性表的优点是()。 (2分)
- 便于插入和删除操作
- 便于随机存取
- 可以动态地分配存储空间
- 不需要占用一片相邻的存储空间
解析:顺序表的特性。
2-9若长度为n的线性表采用顺序存储结构,那么删除它的第i个数据元素之前,需要它一次向前移动()个数据元素。 (2分)
- n-i
- n+i
- n-i-1
- n-i+1
解析:删除元素,只需要移动ai之后的所有元素,因此是n-i。
2-10若长度为n的线性表采用顺序结构,在第i个数据元素之前插入一个元素,需要它依次向后移动()个元素。 (2分)
- n-i
- n-i+1
- n-i-1
- i
解析:增加结点,移动的次数就是ai以及之后的所有元素,就是n-i+1.
2-11线性表L=(a1, a2 ,……,an )用一维数组表示,假定删除线性表中任一元素的概率相同(都为1/n),则删除一个元素平均需要移动元素的个数是()。 (2分)
- n/2
- (n+1)/2
- (n-1)/2
- n
解析:对于所有的情况一共有n种,所有的移动次数为,对于每种情况出现的概率都是(1/n),因此是(n-1)/2。
编程题:
若一个线性表L采用顺序存储结构存储,其中所有的元素为整数。设计一个算法,删除元素值在[x,y]之间的所有元素,要求算法的时间复杂度为O(n),空间复杂度为O(1)。
输入格式:
三行数据,第一行是顺序表的元素个数,第二行是顺序表的元素,第三行是x和y。
输出格式:
删除元素值在[x,y]之间的所有元素后的顺序表。
输入样例:
10
5 1 9 10 67 12 8 33 6 2
3 10
输出样例:
1 67 12 33 2
解析:其实完全可以不删除,也就是满足条件不输出,不满足就输出,但是在这里还是练习一下删除。
#include <bits/stdc++.h>
using namespace std;
typedef int ElemType;
const int MAX_SIZE = 10000;
struct sqlist
{
ElemType *elem;
int length;
} SqList;
int x, y;
void InitList()
{
SqList.elem = new ElemType[SqList.length];
return ;
}
void Delete(int pos)
{
for(int i = pos; i < SqList.length - 1; i++)
SqList.elem[i] = SqList.elem[i + 1];
SqList.length--;
}
void DeleteList(int l, int r)
{
if(SqList.length == 0)
return ;
for(int i = 0; i < SqList.length; i++)
{
if(SqList.elem[i] >= l && SqList.elem[i] <= r)
Delete(i--);
}
return ;
}
int main()
{
cin >> SqList.length;
InitList();
for(int i = 0; i < SqList.length; i++)
cin >> SqList.elem[i];
cin >> x >> y;
DeleteList(x, y);
for(int i = 0; i < SqList.length; i++)
{
cout << SqList.elem[i];
if(i == SqList.length - 1)
cout << endl;
else
cout << " ";
}
delete []SqList.elem;
return 0;
}