顺序表上基本操作的实现
顺序表定义
#define MaxSize 50
typedef struct{
ElemType data[MaxSize]; // 以数组方式存储元素
// ElemType *data; #用于动态分配数组
int length; // 顺序表当前大小
// int MaxSize, length; #数组最大容量和当前长度
}SqList; // 用typedef语句将结构体定义为SqList类型
// C初始动态分配语句 强制类型转换为 ElemType* 确保初始化数据元素大小与表内元素大小相同
L.data = (ElemType*)malloc(sizeof(ElemType)*InitSize);
// C++初始动态分配语句
L.data = new ElemType[InitSize];
- 插入
在顺序表L的第 i i i个位置插入新元素 e e e,若 i i i输入不合法,返回false,表示插入失败;否则将顺序表的第 i i i个元素及其后所有元素顺移一位,在 i i i插入新元素 e e e,然后表长增加1,返回true。
移动平均次数为 ∑ i = 1 n + 1 p i ( n − i + 1 ) = ∑ i = 1 n + 1 1 n + 1 ( n − i + 1 ) = 1 n + 1 ∑ i = 1 n + 1 ( n − i + 1 ) = 1 n + 1 n ( n + 1 ) 2 = n 2 \sum_{i=1}^{n+1}p_i(n-i+1)=\sum_{i=1}^{n+1}\frac{1}{n+1}(n-i+1)=\frac{1}{n+1}\sum_{i=1}^{n+1}(n-i+1)=\frac{1}{n+1}\frac{n(n+1)}{2}=\frac{n}{2} ∑i=1n+1pi(n−i+1)=∑i=1n+1n+11(n−i+1)=n+11∑i=1n+1(n−i+1)=n+112n(n+1)=2n
因此平均时间复杂度为 O ( n ) O(n) O(n)
bool ListInsert(SqList &L, int i, ElemType e){
if(i<1 || i>L.length+1) // 判断插入位置是否有效
return false;
if(L.length>=Maxsize) // 判断表是否已满
return false;
for(int j=L.length;j>=i;j--) // 将位置i之后的元素向后顺移一位以腾出空间插入i元素
L.data[j]=L.data[j-1];
L.data[i-1]=e // 这里i-1是因为数组以0开始
L.length++;
return true;
- 删除
删除顺序表L中第 i i i个位置的元素,成功则返回true并将删除元素赋值给 e e e,否则返回false。
移动平均次数为 ∑ i = 1 n p i ( n − i ) = ∑ i = 1 n 1 n ( n − i ) = 1 n ∑ i = 1 n ( n − i ) = 1 n n ( n − 1 ) 2 = n − 1 2 \sum_{i=1}^{n}p_i(n-i)=\sum_{i=1}^{n}\frac{1}{n}(n-i)=\frac{1}{n}\sum_{i=1}^{n}(n-i)=\frac{1}{n}\frac{n(n-1)}{2}=\frac{n-1}{2} ∑i=1npi(n−i)=∑i=1nn1(n−i)=n1∑i=1n(n−i)=n12n(n−1)=2n−1
因此平均时间复杂度为 O ( n ) O(n) O(n)
bool ListDelete(SqList &L, int i, ElemType &e){
if(i<1 || i>L.length+1) // 判断删除位置是否有效
return false;
e = L.data[i-1];
for(int j=i;j<L.length;j++)
L.data[j-1]=L.data[j];
L.length--;
return true;
}
- 按值查找
在顺序表L中查找第一个元素值等于e的元素,并返回其位序。
最好情况: O ( 1 ) O(1) O(1)
最坏情况: O ( n ) O(n) O(n)
平均情况: O ( n ) O(n) O(n)
int LocateElem(SqList L, ElemType e){
int i;
for(i=0;i<L.length;i++)
if(L.data[i]==e)
return i+1;
return 0;
}
习题 2.2
-
从順序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。空出的位置由最后一个元素填补,若顺序表为空则显示出错信息并退出运行。
我的思路:设置变量 m i n min min记录最小元素,设置变量 j j j记录最小元素位置,遍历一遍顺序表之后删除位置j的元素。
函数参数为顺序表和接收被删除的最小元素。bool DeleteMin(SqList &L,ElemType &e){ if(L.length == 0) return false; int min = L.data[0] int j = 0; for(i=0;i<L.length;i++) if(L.data[i]<min){ min = L.data[i] j = i; } e = min; L.data[j]=L.data[L.length-1]; return true; }
看了标准答案感觉没差多少,他比我少开辟一个min,直接用e来存储最小值。
-
设计一个高效算法,将順序表L的所有元素逆置,要求算法的空间复杂度为 O ( 1 ) O(1) O(1).
我的思路:(数组下标)第i个元素和第n-i-1元素交换,到中间停下。void Reverse(SqList &L){ int i; ElemType temp; for(i=0;i<n/2;i++){ temp = L.data[i] L.data[i]=L.data[n-i-1] L.data[n-i-1]=temp; } }
看了标答,没什么问题。
-
对长度为”的順序表编写一个时间复杂度为 O ( n ) O(n) O(n)、空间复杂度为 O ( 1 ) O(1) O(1)的算法,该算法删除线性表中所有值为x的数据元素。
我的思路:做这题的时候已经看过两次答案了……所以基本思路一样。设置变量k记录表中当前位置。变量i用来遍历表,当表中i元素为x时,i++,k不变,这样遍历一遍之后表中x的元素会被取代。最后记得把表长改了。void Delete_X(SqList &L, ElemType x){ int i,k=0; for(i=0;i<L.length;i++){ if(L.data[i]!=x){ L.data[k++]=L.data[i]; } } L.length = k; }
-
从有序順序表中删除其值在给定值s与t之间(要求s<t)的所有元素,如果s或t不合理或顺序表为空,则显示出错信息并退出运行.
我的思路:因为是有序顺序表,所以只要记录端点值和长度len然后把顺序变向前移动len个,再修改表长就可以了。bool Delete_s_t(SqList &L, ElemType s, ElemType t){ int i,j; if(s>=t || L.length==0) return false; for(i=0;i<L.length&&L.data[i<s;i++) // 空循环,主要目的是把i移到第一个大于s的元素 if(i>=L.length) return false; for(j=i;j<L.length&&L.data[j]<=t;j++); // 空循环,主要目的是把j移到第一个大于t的元素 for(;j<L.length;i++,j++) L.data[i]=L.data[j]; L.length = i; return true; }
自己写的代码好像逻辑有问题,这个是答案。
-
从順序表中删除其值在给定值s与t之间(包含s和t,要求s<t)的所有元素,如果s或t不合理或顺序表为空,则显示出错信息并退出运行.
我的思路:其实这题和第三题一样,只要把判断条件改一下就行。bool Delete_s_t2(SqList &L, ElemType x){ int i,k=0; if(L.length==0 || s>=t)