01.从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。空出的位置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行。
算法思想:搜索整个顺序表,查找最小值,删除最小值并记住其所在的位置,结束后将最后一个元素补到该最小值的位置。
//参考答案
bool Del_Min(sqList &L,ElemType &value){
//删除顺序表L中最小值元素结点,并通过引用型参数value返回其值
//若删除成功,则返回true;否则返回false
if(L.length == 0){
return false; //表空,中止操作
}
value = L.data[0];
int pos = 0; //假设0号元素的值最小
for(int i = 1;i < L.length;i++){ //循环遍历寻找具有最小值的元素
if(L.data[i] < value){ //让value记忆当前具有最小值的元素
value = L.data[i];
pos = i;
}
}
L.data[pos] = L.data[L.length-1]; //空出来的位置由最后一个元素填补。
L.length--;
return true;
}
02.设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)。
算法思想:扫描顺序表L的前半部分元素,将L.data[i]与L.data[L.length-i-1]互换位置。其中0<=i<L.length/2。
//自己敲
void Reserve(sqList &L){
int temp; //设置中间变量
for(int i = 0;i<L.length/2;i++){
temp = L.data[i];
L.data[i] = L.data[L.length-i-1];
L.data[L.length-i-1] = temp;
}
}
//答案
temp的类型不一样。
Elemtype temp; //辅助变量。
03.对长度为n的顺序表L,编写一个时间复杂度为O(n)、空间复杂度为O(1)的算法,该算法删除线性表中所有值为x的数据元素。
算法思想:搜索整个顺序表,查找到值为x的元素的位置,将其删除。
//自己敲
void Delete(sqlList &L){
scanf("x = %d",&x);
for(int i = 0;i<L.length;i++){
if(L.data[i] == x){
//删除操作不知道怎么描述
}
}
}
//答案
//解法一:用k记录顺序表L中不等于x的元素个数(即需要保存的元素个数),扫描时将不等于x的元素移动到下标k的位置,并更新k值。扫描结束后修改L的长度。
void del_x_l(SqList &L,Elemtype x){
int k=0,i; //记录值不等于x的元素个数
for(i=0;i<L.length;i++){
if(L.data[i] != x){
L.data[k] = L.data[i];
k++; //不等于x的元素增加1
}
}
L.length=k; //顺序表的长度等于k
}
04 从有序顺序表中删除其值在给定值s与t之间(要求s<t)的所有元素,若s或t不合理或顺序表为空,则显示出错信息并退出运行。
算法思想:因为该表是有序的顺序表,所以值在s与t之间的元素是连着的,只需找到第一个比s大的以及第一个比t大的元素,中间的值就是需要找的所有元素。
要想将这段元素删除,只需直接将后面的元素前移
//自己敲
void del_s_t(SqlList &L,Elemtype s,t){
if(L.length == 0||s >= t){
return false; //表为空或者s大于等于t
}
for(int i=0;i<L.length;i++){
if(L.data[i]>s){
//找到后不知该如何记录
}
}
for(int j=0;j<L.length;j++){
if(L.data[j]>t){
//找到后不知该如何记录
}
}
}
//答案
bool Del_s_t2(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++); //寻找值大于等于s的第一个元素
if(i>=L.length)
return false; //所有元素值均小于s,返回
for(j=i;j<L.length&&L.data[j]<=t;j++); //寻找值大于t的第一个元素
for(j<L.length;i++,j++)
L.data[i]=L.data[j]; //前移,填补被删元素位置
L.length = i;
return true;
}
05 从顺序表中删除其值在给定值s与t之间(包含s与t,要求s<t)的所有元素,若s或t不合理或顺序表为空,则显示出错信息并退出运行。
算法思想:从前向后扫描顺序表L,用k记录下元素值在s到t之间元素的个数(初始时k为0)。对于当前扫描的元素,若其值不在s到t之间,则前移k个位置,否则执行k++。由于这样每个不在s到t之间的元素仅移动一次,因此算法效率高。
//答案
bool Del_s_t(SqList &L,ElemType s,ElemType t){
int i,k=0;
if(L.length == 0||s>=t)
return false;
for(i=0;i<L.length;i++){
if(L.data[i]>=s&&L.data[j]<=t)
k++;
else
L.data[i-k]=L.data[i]; //当前元素前移k个位置
}
L.length- = k; //长度减少
return true;
}
06 从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同。
算法思想:顺序表为有序表,那么值相等的元素一定是连续的,初始时将第一个元素视为非重复元素的有序表,之后依次判断后面的元素是否与前面非重复有序表的最后一个元素相同,若相同,则继续向后判断,若不同,则插入前面的非重复有序表的最后,直至判断到表尾为止。
bool Delete_Same(SeqList &L){
if(L.length == 0)
return false;
int i,j; //i存储第一个不相同的元素,j为工作指针
for(i=0,j=1;j<L.length;j++)
if(L.data[i] != L.data[j]) //查找下一个与上个元素值不同的元素
L.data[++i]=L.data[j]; //找到后,将元素前移
L.lengh=i+1;
return true;
}
07 将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。
算法思想:将两个有序顺序表一一比较,判断哪个表还有剩余,将剩余部分直接加在新的表后即可。
//答案
bool Merge(SeqList A,SeqList B,SeqList &C){
if(A.length+B.length >C.maxsize) //大于顺序表的最大长度
return false;
int i,j,k=0;
while(i<A.length&&j<B.length){ //循环,两两比较,小者存入结果表
if(A.data[i]<=B.data[j])
C.data[k++]=A.data[i++];
else
C.data[k++]=B.data[j++];
}
while(i<A.length) //还剩一个没有比较完的顺序表
C.data[k++]=A.data[i++];
while(j<B.length)
C.data[k++]=B.data[j++];
C.length=k;
return true;
}
08 已知在一维数组A【m+n】中依次存放两个线性表(a1,a2…am)和(b1,b2…bn),编写一个函数,将两个顺序表的位置互换,即将(b1,b2…bn)放在(a1,a2…am)的前边。
算法思想:根据逆置算法,先将数组A中整体逆置,成为(bn,…b2,b1,am,…a2,a1),然后分别对b和a进行逆置。
//答案
typedef int DataType;
void Reverse(DataType A[],int left,int right,int arraySize){
if(left>=right||right>=arraySize)
return false;
int mid=(left+right)/2;
for(int i=0;i<mid-left;i++){
DataType temp=A[left+i];
A[left+i]=A[right-i];
A[right-i]=temp;
}
}
void Exchange(DataType A[],int m,int n,int arraySize){
Reverse(A,0,m+n-1,arraySize);
Reverse(A,0,n-1,arraySize);
Reverse(A,n,m+n-1,arraySize);
}
09 线性表(a1,a2,a3…an)中的元素递增有序且按顺序存储于计算机内。要求设计一个算法,完成用最少时间在表中查找数值为x的元素,若找到,则将其与后继元素位置相交换,若找不到,则将其插入表中并使表中元素仍递增有序。
算法思想:采用最短的时间,应该使用折半查找法。
//答案
void SearchExchangeInsert(ElemType A[],ElemType x){
int low=0,high=n-1,mid; //low和high只想顺序表下界和上界的下标
while(low<=high){
mid=(low+high)/2 //找中间位置
if(A[mid]==x) break //找到x,退出while循环
else if(A[mid]<x) low=mid+1; //到中点mid的右半部去查
else high=mid-1; //到中点mid的左半部去查
}
//下面两个if语句只会执行一个
if(A[mid]==x&& mid!=n-1){ //若最后一个元素与x相等,则不存在与其后继交换
t=A[mid]
A[mid]=A[mid+1];
A[mid+1]=t;
}
if(low>high){ //查找失败,插入数据元素x
for(i=n-1;i>high;i--)
A[i+1]=A[i]; //后移元素
A[i+1]=x; //插入x
}
}