习题整理
顺序表
- 线性表的顺序存储是一种()。
A. 随机存取的存储结构
B. 顺序存取的存储结构
C. 索引存取的存储结构
D. 散列存取的存储结构
【答案】: A
【解释】:存取方式指的是读写方式。顺序表是一种支持随机存取的存储结构,根据起始地址加上元素的序号,可以很方便地访问任意一个元素,这就是随机存取的概念。
【知识补充】:
- Q:从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删除元素的值。空出的位置由最后一个元素填补,若顺序表为空则显示出错信息并退出运行。
A:
解答:
算法思想:搜索整个顺序表,查找最小元素并记住其位置,搜索结束后用最后一个元素填补空出的原最小值元素的位置。
代码:
bool Del_Min(sqList &L,ElemType & value){
//删除顺序表L中最小元素结点,并通过引用型参数返回其值
//若删除成功,则返回true,否则,返回false
if(L.length==0)
return false;
value =L.data[0];
int idx=0;
for(int i=1;i<L.length;i++){
if(L.data[i]<value){
value = L.data[i];// value记录当前最小元素
idx = i;
}
}
L.data[i] = L.data[L.length-1];//空出的位置由最后的元素填补
L.length--;
return true;
}
*Q:设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1).
*A:
算法思想: 扫描顺序表的前半部分元素,将其与后半部分对应元素交换。
代码:
void Reverse(sqList &L){
Elemtype tmp;//辅助变量
for(int i=0;i<L.length/2;i++){
tmp = L.data[i];
L.data[i] = L.data[L.length-i-1];
L.data[L.length-i-1] = tmp;
}
}
*Q:对长度为n的顺序表L,编写一个时间复杂度为O(n)、空间复杂度为O(1)的算法,该算法删除线性表中所有值为x的数据元素。
A:
*解法一:用k记录顺序表L中不等于x的元素的个数,边扫描L边统计k,并将不等于x的元素向前移动k个位置,最后修改L的长度。
void delete_x(sqList &L,Elemtype x){
//本算法实现删除顺序表L中所有值为x的数据元素
int k = 0;//记录值不等于x的元素个数
for(int i = 0; i < L.length; i++){
if(L.data[i] != x){
L.data[k] = L.data[i];
k++;
}
}
L.length = k;
}
*解法二:用k记录顺序表L中等于x的元素个数,边扫描L边统计k,并将不等于x的元素前移k个位置,最后修改顺序表L的长度。
void delete_x(sqList &L,Elemtype x){
int k = 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;//顺序表长度递减
}
解法3:设头尾指针分别从顺序表头尾遍历,如果头指针遍历到元素值等于x,那么将尾指针对应元素值放到头指针位置,直到头尾指针相遇。
这种做法可能会导致原顺序表中的位置关系发生变化。
void delete_x(sqList &L,Elemtype x){
int i=0;//定义头指针从头遍历顺序表
int j = L.length-1;//定义尾指针从后遍历顺序表
while(i<j){
if(L.data[i]==x){
while(L.data[j] == x && i < j)
j--;//j从后向前找到第一个不等于x的元素
if(i>=j) break;//如果头尾指针相遇则停止!
L.data[i] = L.data[j];
j--;
}
else
i++;//头指针向后遍历
}
L.length = i+1;
}
- Q:从顺序表中删除其值在给定值s与t之间(要求s<t)的所有元素,如果s或t不合理或顺序表为空,则显示出错信息并退出运行。
*A:
解法1:
算法思想: 用k记录顺序表中在s与t之间的元素的个数,边扫描边统计k,最后修改顺序表的长度。
bool delete_s2t(sqList &L, Elemtype s,Elemtype t){
if(L.length==0 || s>=t)
return false;
k = 0;
for(i = 0;i < L.length; i++){
if(L.data[i] >=s && L.data[i] <= t){
k++;
}
else{
L.data[i-k] = L.data[i];
}
}
L.length = L.length - k;
return true;
}
解法2:
算法思想: 用k记录顺序表中不在s与t之间的元素的个数,边扫描边统计k,最后修改顺序表的长度。
bool delete_s2t(sqList &L,Elemtype s,Elemtype t){
if(L.length == 0 || s>=t)
// throw("顺序表不能为空
return false;
k = 0;
for(i = 0; i < L.length ; i++){
if(L.data[i]<s || L.data[i] >t){
L.data[k] = L.data[i];
k++;
}
}
L.length = k;
return true;
}
!如果题目改为有序顺序表呢?
bool Del_s2t(sqList &L,Elemtype s,Elemtpye 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的元素的索引
//i,j
for(;j<L.length;j++,i++)
L.data[i] = data[j];
L.length = i;
return true;
}
- Q:从有序顺序表中删除所有其值重复的元素,使表中所有元素值均不同。
算法思想:
类比插入排序,初始时将第一个元素视为非重复的有序表。之后一次判断后面的元素是否与前面非重复有序表的最后一个元素相同,若相同则继续向后判断,若不同则插入到前面的非重复有序表的最后,直至判断到表尾为止。
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.length = i+1;
return true;
}
*Q: 将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。
bool merge(SeqList A,SeqList B,SeqList &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)
C.data[k++] = A.data[i++];
while(j<B.length)
C.data[k++] = B.data[i++];
C.length = k;
return true;
}
*Q : 已知一维数组A[m+n]中依次存放两个线性表(a_1,a_2,...a_m)和(b_1,b_2,b_3,...b_n)试编写一个函数,将数组中两个顺序表的位置互换,即将(b_1,b_2,b_3,...b_n)放在(a_1,a_2,...a_m)之前。
算法思路:
先将数组A[m+n]中的所有元素逆置,然后分别对前n个元素和后m个元素逆置就可以得到两个顺序表互换位置。
void Reverse(DataType A[],int left,int right,int arraySize){//left right 为下标索引
//$逆转(a_left,a_2,...a_right)为(a_right,a_right-1,...a_left)$
if(left>=right || right>=arraySize)
return ;
int mid = (left+right)/2;
for(int i=0; i<=mid-left; i++){
DataType tmp = A[left+i];
A[left+i] = A[right-i];
A[right-i] = tmp;
}
return ;
}
void Exchange(DataType A[],int m,int n,int arraySize){
//数组A[m+n]中,从0到m-1存放顺序表$(a_1,a_2,...,a_m)$,
//从m到m+n-1存放顺序表$(b_1,b_2,...b_n)$,算法将这两个表位置互换。
Reverse(A,0,m+n-1,arraySize);
Reverse(A,0,n-1,arraySize);
Reverse(A,n,n+m-1,arraySize);
}
*Q:线性表((a_1,a_2,a_3,...a_n))中的元素递增有序且按顺序存储于计算机内。要求设计一算法,完成用最少时间在表中查找数值为x的元素,若找到则将其与后继元素位置相交换,否则将其插入表内使得表中元素仍递增有序。
算法思想:使用折半查找的思想
void SearchExchangeInsert(ElemType A[], int n, ElemType x){
int low = 0, high = n-1, mid;
while(low <= high){
mid = (low+high)/2;
if(A[mid] == x)
break;
else if(A[mid] < x){
low = mid+1;
}
else{
high = mid-1;
}
}
if(A[mid] == x && mid != n-1){
ElemType t = A[mid];
A[mid] = A[mid+1];
A[mid+1] = t;
}
if(low > high){ //查找失败,插入数据元素
for(int i=n-1;i>high;i--) A[i+1] = A[i];//后移元素
A[i+1] = x;//插入x
}
}
*Q : [2010统考真题] 数组元素循环左移p个位置。
算法思想: