1.从顺序表中删除最小值元素(唯一)并由函数返回被删元素的值,空出的位置由最后一个元素填补,若顺序表为空,显示出错误信息并退出运行
算法思想:假设数组第一个元素为最小元素,再遍历数组元素与该元素比较,如果比该最小元素小,则更新最小元素值,并记录该最小元素值的位置
typedef struct{
ElemType val[MaxSize];
int length;
}SqList;
void Del_min(SqList &L,ElemType &value){//参数为引用型,用来返回值,因为会对原值修改
if(L.length == 0){
printf("数组为空");
}
ElemType min = L.val[0];
int i,pos;//pos记录最小值元素的位置
for(i = 1;i < L.length;i++){
if(L.val[i] < min){
min = L.val[i];
pos=i;
}
}
value = min;
L.val[pos] = L.val[i-1];
L.length--;
}
2.设计一个算法,将顺序表逆置,要求空间复杂度为o(1)
算法思想:双下标相向互换,单下标折半互换
//双下标相向互换
void Revese_L(SqList &L){
int i = 0,j = L.length-1;
while(i < j){
ElemType temp = L.val[i];
L.val[i] = L.val[j];
L.val[j] = temp;
i++;
j--;
}
}
//单下标折半互换
void Revese_L(SqList &L){
int i = 0;
while(i < L.length/2){
ElemType temp = L.val[i];
L.val[i] = L.val[L.length-1-i];
L.val[L.length-1-i] = temp;
i++;
}
}
3.对长度为n的顺序表L,编写一个时间复杂度为o(n)、空间复杂度为o(1)的算法,该算法删除线性表中所有值为x的数据元素
算法思想:
①边扫描数组边记录下等于x的元素个数k,将不等于x的元素向前移动k各位置
②边扫描数组边记录不等于x的元素个数k,将不等于x的元素赋值在k下标下,并更新k值
//方式一
void Delete_x(SqList &L,ElemType x){
int k = 0;//记录x的个数
for(int i = 0;i < L.length;i++){
if(L.val[i] == x){
k++;
}else{
L.val[i-k] = L.val[i];
}
}
L.length -= k;
}
//方式二
void Delete_x(SqList &L,ElemType x){
int k = 0;//记录不等于x的元素个数
for(int i = 0; i< L.length;i++){
if(L.val[i] != x){
L.val[k] = L.val[i];
k++;
}
L.length = k;
}
4.从有序顺序表中删除其值在给定值s与t之间(s < t)的所有元素,若s或t不合理或顺序表为空,则显示错误信息并退出运行
算法思想:由于是有序表使以s与t之间的元素必连续存放,删除操作即从t(或大于t的第一个元素)的元素)起从s后第一个元素起开始覆盖
int Delete_s_t(SqList &L,ElemType s,ElemType t){
if(L.length == 0 || s >= t){
return 0;
}
//寻找s后的第一个元素位置
int i = 0;
while(i < L.length && L.val[i] <= s){
i++;
}
if(i == L.length-1){
return 0;
}
//寻找t或大于t的第一个元素所在位置
int j = i;
while(j < L.length && L.val[j] < t){
j++;
}
//删除操作
for(;j < L.length;j++,i++){
L.val[i] = L.val[j];
}
L.length = i;
return 1;
}
5.从顺序表中删除在给定值s与t间的元素(包括s和t)
算法思想:解法和代码类似于第3题
//方式一
int Delete_x(SqList &L,ElemType s,ElemType t){
if(L.length == 0 || s >= t){
return 0;
}
int k = 0;//记录在[s,t]上的元素个数
for(int i = 0;i < L.length;i++){
if(L.val[i] >= s && L.val[i] <= t){
k++;
}else{
L.val[i-k] = L.val[i];
}
}
L.length -= k;
return 1;
}
//方式二
int Delete_x(SqList &L,ElemType x){
if(L.length == 0 || s >= t){
return 0;
}
int k = 0;//记录不在[s,t]上的元素个数
for(int i = 0; i< L.length;i++){
if(L.val[i] < s || L.val[i] > t){
L.val[k] = L.val[i];
k++;
}
L.length = k;
return 1;
}
6.从有序顺序表中删除其值重复的元素,使表中元素各不相同
算法思想:由于有序顺序表,值重复的元素必定在一起,初始时将第一个元素归为非重复的有序表,从第二个元素起开始遍历,判断当前非重复有序表表尾元素是否与当前遍历元素相同,若相同,则继续向后遍历,若不同,将其插入非重复有序表的表尾
Void Delete_Common(SqList &L){
for(int i = 0,j = 1;j < L.length;j++){
if(L.val[i] != L.val[j]){//判断当前非重复有序表表尾元素是否与当前遍历元素相同
L.val[++i] = L.val[j];//不同将该元素插入非重复有序表表尾
}
}
L.length = i+1;
}
7.将两个有序表(设升序)合并成一个新的有序表,并由函数返回结果有序表
算法思想:同时遍历两个有序表,比较表中元素大小,将较小的赋值到结果表中,直至其中一个有序表遍历结束,再将未遍历完的有序表中的元素赋值到结果表中
bool merge(SqList L1,SqList L2,SqList &L){//L为结果表
if(L1.length + L2.length > MaxSize){//MaxSize是定义的顺序表的最大长度
return false;
}
int i = 0,j = 0,k = 0;
while(i < L1.length && j < L2.length){
if(L1.val[i] < L2.val[j]){
L.val[k++] = L1.val[i++];
}else{
L.val[k++] = L2.val[j++];
}
}
//将未遍历完的顺序表赋值到结果表中
while(i < L1.length){
L.val[k++] = L1.val[i++];
}
while(j < L2.length){
L.val[k++] = L2.val[j++];
}
C.length = k;
return true;
}
8.一维数组A[m + n]中存放两个线性表(a1,a2,a3,...am)和(b1,b2,b3,...,bn),试编写算法将数组
里的两个顺序表位置互换
算法思想:先将两个线性表各自反转,再对整个数组反转
void Revese(EmleType A[],int left,int right,int ArraySize){
if(left >= right || right >= ArraySize || left < 0){
return;
}
while(left < right){//双下标相向互换逆置
EmleType temp = A[left];
A[left] = A[right];
A[right] = temp;
left++;
right--;
}
}
void ExchangePos(ElemType A[],int m,int n,int ArraySize){
Revese(A,0,m-1,ArraySize);
Revese(A,m,m+n-1,ArraySize);
Revese(0,m+n-1,ArraySize);
}
9.线性表(a1,a2,a3,...,an)中的元素递增有序且按顺序存储在计算机内,设计一个算法完成用最少时间在表中查找数值为x的元素,若找到,则将其与后继元素位置交换,若找不到,则将其插入表中使表中元素递增有序
算法思想:顺序表且有序用折半查找时间复杂度最低,为O(log2n)
注意:将折半查找算法写在主函数中,其查找失败时的插入位置一定是high+1,即low所在位置
//折半查找
int Binary_Search(SqList L,Elemtype x){
int low = 0,high = L.length-1;
while(low <= high){
int mid = (low + high)/2;
if(L.val[mid] == x){
return mid;//查找成功,返回其数组下标
}else if(L.val[mid] > x){
high = mid-1;
}else{
low = mid+1;
}
}
return -1;//查找失败,返回-1
}
void SearchExchangeInsert(SqList &L,Elemtype x){
int index = Binary_Search(L,x);
if(index != -1 && index != L.length-1){//查找成功且不是最后一个元素,与后继元素交换位置
ElemType temp = L.val[index];
L.val[index] = L.val[index+1];
L.val[index+1] = temp;
}else{//查找失败,插入并使其递增有序
//寻找插入位置
int i = 0;
while(L.val[i] <= x) i++;
for(int j = L.length-1;j >= i;j--){
L.val[j+1] = L.val[j];
}
L.val[i] = x;
}
}
10.设将n(n > 1)个整数存放到一维数组R中,设计一个在时间和空间两方面都尽可能高效的算法将R中保存的序列循环左移
算法思想:解法和代码同第8题,将0-p-1位置和p-n-1位置看作两个线性表分别逆置,再整体对数组逆置
11.找两个等长升序序列的中位数
算法思想:
12.找出一维整数数组的主元素;主元素:其元素个数大于数组长度的一半
算法思想:Boyer-Moore 投票算法
count初值为0,遍历数组
①先判断,当count初值为0时,将当前元素赋值给候选主元素candidate
②继续遍历,当数组元素等于candidate时count加1,否则count减一
遍历结束后,当count大于0时,candidate即为主元素,否则不存在主元素
int SearchMainElem(ElemType A[],int ArraySize){
int count = 0,candidate;
for(int i = 0;i < ArraySize;i++){
if(count == 0){
candidate = A[i];
}
count += A[i] == candidate ? 1 : -1;
}
if(count > 0){
return candidate;
}
return -1;
}
13.找出长度为n的一维整型数组的未出现的最小正整数,且数组元素的大小<=n
算法思想:由于数组元素的大小<=n,且要求找最小正整数,故申请一个长度为n的数组空间当作存在标记数组,将原数组的正整数(1-n)当作该存在标记数组的数组下标,遍历原数组,将其数组值设置1当作存在标记,再遍历存在标记数组,第一个为0的数组元素的下标+1即为原数组中未出现的最小正整数
int Seach_Min(int nums[],int n){
//创建并初始化存在标记数组
int* arr = (int*)malloc(sizeof(int)*n);
for(int i = 0;i < n;i++){
arr[i] = 0;
}
//将原数组中的正整数设置存在标记
for(int i = 0;i < n;i++){
if(nums[i] > 0 && arr[nums[i]-1] != 1){
arr[nums[i]-1] = 1;//设置为1,代表原数组中存在该元素
}
}
//遍历存在标记数组,找到第一个元素值为0的数组下标
int target = 0;
for(int i = 0;i < n;i++){
if(!arr[i]){
target = i;
break;
}
}
return target+1;
}