1.线性表结构定义
typedef struct {
int a[100];//或定义MaxSize
int length;
}SqList;
其中length记录线性表长度,a是数据域。
2.根据位置i获取相应位置数据元素的内容
int GetElem(SqList L, int i, int& e)
{
if (L.length == 0 || i<1 || i>L.length)
{
return 0;
}
e = L.a[i - 1];
}
对位置的解释:位置是从第一开始的,也就是1<=i<=L.length,位置对应的索引为位置-1。
因此if里的条件遍很好理解了:L.length=0说明是空表,而位置不可能小于1,也不可能大于L.length。
最后把对应位置的值赋给e即可。注意由于e发生变化,因此使用引用,并且数组对应的数字为索引而不是位置。
时间复杂度:O(1)
示例:
int main() {
SqList L;
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
L.a[i] = i + 1;//初始化线性表
for (int i = 0; i < n; i++)
printf("%d ",L.a[i]);
cout << endl;
L.length = n;
int e;
GetElem(L, 5, e);//得到第五个位置的元素
cout << e;
}
3.顺序表的查找
根据元素的值,查找对应元素的位置,如果没有这个值的元素则返回0,查找到则返回位置
int LocateElem(SqList L, int e) {
for (int i = 0; i < L.length; i++)
{
if (L.a[i] == e)
return i + 1;
}
return 0;//全部查找完毕也没有返回值,说明没有该元素,故返回0
}
示例:
int main() {
SqList L;
int n;
scanf("%d", &n);
L.length = n;//注意要给L.length值
for (int i = 0; i < n; i++)
L.a[i] = i + 1;
for (int i = 0; i < n; i++)
printf("%d ",L.a[i]);
cout << endl;
cout << LocateElem(L, 5);//找值为5的元素的位置
}
如果有多个符合条件的元素,则返回索引最小的一个(因为是从前往后搜索的)。
时间复杂度:O(n)
4.顺序表的插入
int InsertElem(SqList& L, int i, int e) {//在i后面插入,i表示位置而不是索引,索引=i-1
int j;
if (i<1 || i>L.length + 1 || L.length == MaxSize)
return 0;
for (j = L.length - 1; j >= i - 1; j--)
{
L.a[j + 1] = L.a[j];
}
L.a[i-1] = e;
L.length++;
return 1;
}
顺序表的插入主要是理解两个问题:1.插入的范围 2.数据的变化
1.插入的范围:
由于i表示位置,而且插入是插入的元素在第i个位置,可以是第一个,也可以是第L.length+1个(最后一个后面),因此 1<=i<=L.length+1
2、数据的变化:
数据的变化需要为插入的地方腾出空间,并且不影响后面的数据。也就是从最后一个元素开始,让元素后面的位置等于该元素的值,一直到要插入地方的数据也移动完毕。不能从前往后开始,因为这样会导致数据被覆盖(第二个等于第一个,第三个等于第二个,结果第三个与第一个相等,这样肯定不对)。
设置一个代表索引的值j,j从L.length-1开始,直到j<i-1结束,也就是只要符合j>=i-1即可。然后移动的操作是:L.a[j+1]=L.a[j] (自己的后一项等于自己)
最后,把值赋给位置i(即索引i-1),表长加一。
时间复杂度:O(n)
示例:
int main() {
SqList L;
int n;
scanf("%d", &n);
L.length = n;
for (int i = 0; i < n; i++)
L.a[i] = i + 1;//初始化线性表
for (int i = 0; i < n; i++)
printf("%d ",L.a[i]);
cout << endl;
InsertElem(L, 4, 9);//把“9”插入第四个位置
for(int i = 0; i < L.length; i++)
{
printf("%d ", L.a[i]);
}
}
5.顺序表的删除
int DeleteElem(SqList& L, int i) {
if (i<1 || i>L.length)
return 0;
for (int j = i-1; j <= L.length - 2; j++)
{
L.a[j] = L.a[j+1];
}//最后两个元素会相同,但因为表长减一,因此忽略了最后一个元素
L.length--;//表长减一
return 1;
}
1.删除的范围:
可以删除的极限位置:第一个与最后一个,即i=1与i=L.length,因此1<=i<=L.length
2.数据的变化:
既然是删除,那么就是从删除的索引(i-1)开始,让后一个覆盖自己,直到L.length-2被L.length-1覆盖(注意是索引),因为L.length-1之后就没有元素了,因此L.length-1不会被覆盖。但由于删除之后表长减一,因此忽略不计了。
这样应该能更好理解:从索引i-1开始被覆盖,直到索引L.length-2被覆盖
时间复杂度:O(n)
示例:
int main() {
SqList L;
int n;
scanf("%d", &n);
L.length = n;
for (int i = 0; i < n; i++)
L.a[i] = i + 1;
for (int i = 0; i < n; i++)
printf("%d ",L.a[i]);
cout << endl;
DeleteElem(L, 4);//删除第四个位置的元素
for(int i = 0; i < L.length; i++)
{
printf("%d ", L.a[i]);
}
}
6.其余操作
(1)顺序表的销毁
void DestroyList(SqList& L) {
if (L.a)
delete L.a;
}
如果数据域不为空则销毁数据域
(2)顺序表求长度
int GetLength(SqList L) {
return L.length;
}
(3)顺序表判断是否为空
int IsEmpty(SqList L) {
if (L.length == 0)
return 1;
else
return 0;
}
根据L.length进行判断