线性表
从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。空出的位置由最后一个元素填补,若顺序表为空则显示出错信息并退出运行。
算法思想:搜索整个顺序表,查找最小值元素并记住其位置,搜索结束后用最后一个元素填空出的原最小值元素的位置。
bool Del_Min(sqList &L, EleType &value)
{
//删除顺序表L中最小值元素节点,并通引用性参数value返回其值
//若删除成功,则返回true;否则返回false
if(L.length==0)
return false; //表空,终止操作返回
value=L.data[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; // 此时,value即为最小值
}
设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)。
算法思想:扫描顺序表L的前半部分元素,对于元素L.data[i](0<=i<L.1 ength/2),
将其与后半部分的对应元素L.data[L.1 ength-i-1]进行交换。
void Reverse(Sqlist &L)
{
Elemtype temp; //辅助变量
for(i=0;i<L.length/2;i++)
{
temp=L.data[i]; //交换L.[data]与L.data[L.length-i-1]
L.data[i]=L.data[L.length-i-1];
L.data[L.length-i-1]=temp;
}
}
对长度为n的顺序表L,编写一个时间复杂度为O(n)、空间复杂度为O(1)的算法,该算法删除线性表中所有值为x的数据元素。
解法一:用k记录顺序表L中不等于x的元素个数(即需要保存的元素个数),边扫描L边统计k
并将不等于x的元素向前移动k个位置,最后修改L的长度
void del_x_1(Sqlist &l,Elemtype x)
{
//本算法实现删除顺序表中所有值为x的数据元素
int k=0; //记录值不等于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; //顺序表L的长度等于k;
}
解法二:用k记录顺序表L中等于x的元素个数,边扫描L边统计k,并将不等于x的元素前移k个位置,最后修改L的长度。
void del_x_2(Sqlist &l,Elemtype x)
{
int k=0,i=0; //k记录值等于x的元素个数
while(i<L.length)
{
if(L.data[i]==x)
k++;
else
L.data[i-k]=L.data[i]; //当前元素前移k个位置
i++;
}
L.length=L.length-k; //顺序表L的长度递减
}
从有序顺序表中删除其值在给定值s与t之间(要求s<t)的所有元素,如果s或t不合理或顺序表为空,则显示出错信息并退出运行
注意:本题与上一题的区别。因为是有序表,所以删除的元素必然是相连的整体。
算法思想:先寻找值大于等于s的第一个元素(第一个删除的元素),
然后寻找值大于t的第个元素(最后一个删除的元素的下一个元素),要将这段元素删除,只需直接将后面的元素前移
bool Del_s_t2(SqList &L,ElemType s, ElemType t)
{
//删除有序表L中值在给定值s与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;
}
从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同
算法思想:注意是有序顺序表,值相同的元素一定在连续的位置上,用类似于直接插入排序的思想,
初始时将第一个元素视为非重复的有序表.之后依次判断后面的元素是否与前面非重复有序表的最后一个元素相同,
若相同则继续向后判断,若不同则插入到前面的非重复有序表的最后,直至判断到表尾为止.
bool. Delete Same(SeqList& L){
if (L.length==0)
return fals;
int i,j; //i存储第一个不相同的元素,j为工作指针
for (1-0,j=1:j<L, length:j++)
if(L.data[i]!=L,data[j]) //查找下一个与上个元素值不同的元素
L.data[++i]=L.data[j]; //找到后,将元素前移
L.length=i+1;
return true;
}
将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。
算法思想:首先,按顺序不断取下两个顺序表表头较小的结点存入新的顺序表中.然后,看哪个表还有剩余,
将剩下的部分加到新的顺序表后面.
注意:本算法的方法非常典型,需牢固掌握.
bool Merga(SeqList A, SeqList B, SeqList &C){
//将有序顺序表A与B合并为一个新的有序顺序表C
if(A.length+B, length>C.maxsize) //大于顺序表的最大长度
return false;
int i=0,j=0, 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) //还剩一个没有比较完的顺序表while(j<B length)
C.data[k++]=B.data[j++]
C.length=k;
return true;
}
已知在一维数组A[m+n]中依次存放两个线性表(a1,a2,a3,…,am)和(b1,b2,b3,…,bn)。试编写一个函数,将数组中两个顺序表的位置互换,即将(b1,b2,b3,…,bn)放在(a1,a2,a3,…,am)的前面。
算法思想:先分别逆,再整体逆
typedef int DataType;
void Reverse(DataType A[],int left, int right, int arraysize){
//逆转(a1eft, aleft+1, aleft+2… aright)为( aright, aright-1,…, aleft)
if (left>=righti lright>=arraysize)
return
int mid=(left+right)/2i
for(int 1=0ii<=mid-leftii++){
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){
/*数组A[m+n]中,从0到m-1存放顺序表(a1,a2,a3,…,am),从m到m+n-1存放顺序表
(b1,b2,b3…,bn),算法将这两个表的位置互换*/
Reverse(A, 0, m+n-1, arraysize);
Reverse(A, 0, n-l, arraysize);
Reverse(A, n, m+n-l, arraysize);
}
线性表(a1a2a,…,an)中的元素递增有序且按顺序存储于计算机内。要求设计一算法,完成用最少时间在表中查找数值为x的元素,若找到则将其与后继元素位置相交换,若找不到则将其插入表中并使表中元素仍递增有序
算法思想:顺序存储的线性表递增有序,可以顺序査找,也可以折半査找.题目要求"用最少的时间在表中查找数值为x的元素",
这里应使用折半查找法
void SearchExchangeInsert(ElemType A[], ElemType x){
int low=0, high=n-1, mid; //1ow和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+l]; A[mid+l]=t;
}
if(low>high){ //查找失败,插入数据元素
for(i=n-1;i>high;i--) A[i+1]=A[i]; //后移元素
A[i+1]=x; //插入x
} //结束插入
}
本题的算法也可写成三个函数:查找函数、交换后继函数与插入函数.写成三个函数的优点是逻辑清晰、易读.
【2010统考真题】设将n(n>1)个整数存放到一维数组R中。设计一个在时间和空间两方面都尽可能高效的算法。将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数据由(X0,X1…,Xn-1变换为(Xp,Xp+1,…,Xn-1,X0,X1,…,Xp-1).要求:
1)给出算法的基本设计思想
2)根据设计思想,采用C或C艹或Java语言描述算法,关键之处给出注释。
1)算法的基本设计思想:可将这个问题视为把数组ab转换成数组ba(a代表数组的前p个元素,b代表数组中余下的n-p个元素),
先将a逆置,再将b逆置,最后将整个逆置得到ba.
设 Reverse函数执行将数组元素逆置的操作,对abcdefgh向左循环移动3(p=3)个位置的过程如下:
Reverse(0,p-1)得到 cbadefgh
Reverse(p,n-1)得到 cbahgfed
Reverse(0,n-1)得到 defghabc;
注: Reverse中,两个参数分别表示数组中待转换元素的始末位置
2)使用C语言描述算法如下:
void Reverse (int RU, int from, int to){
for(i=0; i<(to-from +1)/2;i++)
{temp=R[from+i];R[from+i]=R[to-il;R[to-i]=temp;}
}
void Converse(int R[], int n, int p){
Reverse(R,0, p-1);
Reverse(R,p, n-1);
Reverse(R,0, n-1);
}