5.从有序顺序表中删除其值在给定值s与t之间(包含s和t,要求s<t)的所有元素,若s或t不合理或顺序表为空,则显示错误信息并退出运行。
void DelElms41(Sqlist &L, int s, int t) {
int k = 0;
if (s > t || L.length == 0) {
printf("false");
return;
}//任意一个满足都不会运行程序
for (int 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;
}
void DelElms42(Sqlist &L, int s, int t) {
int i = 0;
int k = 0;
if (s > t || L.length == 0) {
printf("false");
return;
}//任意一个满足都不会运行程序
while (i < L.length) {
if (L.data[i] >= s && L.data[i] <= t) {
k++;
} else {
L.data[i - k] = L.data[i];//当前元素前移k个位置
}
i++;
}
L.length = L.length - k;
}
6.从有序顺序表中删除所有其值重复的元素,使表中元素均不同。
思路:题目重点是"有序"顺序表,说明若其值重复的元素必相邻,遍历顺序表,从第二位元素开始,每次都与前驱元素进行比较判断,若重复则标记
void Del_Re(Sqlist &L) {
int i = 1;
int k = 0;//保存重复元素个数
for (i; i < L.length; i++) {
if (L.data[i] == L.data[i - 1]) {
k++;
} else {
L.data[i - k] = L.data[i];
}
}
L.length = L.length - k;
}
7.将两个有序顺序表合并为一个新的线性表,并由函数返回新的顺序表。
思路:归并算法
Sqlist merge(Sqlist A, Sqlist B,Sqlist &L) {
int i = 0;
int j = 0;
int k = 0;
while (A.length + B.length <= Maxside && i < A.length && j < B.length) {
if (A.data[i] <= B.data[j]) {
L.data[k++] = A.data[i++];
} else{
L.data[k++] = B.data[j++];
}
}
while(i<A.length){
L.data[k++]=A.data[i++];
}
while(j<B.length){
L.data[k++]=B.data[j++];
}
L.length = k;
return L;
}
8.已知在一维数组A[m+n]中依次存放两个线性表(a1,a2,...,am)和(b1,b2,...,bn),编写一个函数,使数组中两个顺序表位置互换。
思路:三次逆转实现,前两次为数组里面的两个线性表各自逆转,第三次为整体逆转。
void reverse2(Sqlist &L, int start, int end) {
int temp = 0;
if (start > end) {
return;
}
for (int i = start, k = 0; i < (start + end) / 2 + 1; k++) { //⚠️此处有"+1",假若忽略此条件,当start+end=1时,不会产生互换。
temp = L.data[i];
L.data[i] = L.data[end - k];
L.data[end - k] = temp;
i++;
}
}
void test08(){
Sqlist L{{1, 2, 3, 44, 11, 22, 33},7};//L.length别忘记
reverse2(L, 0, 2);
reverse2(L, 4, 6);
reverse2(L, 0, 6);
for (int i = 0; i < L.length; i++) {
printf(" %d", L.data[i]);
}
}
9.线性表中的元素递增有序且按顺序存储在计算机内,要求设计一个算法完成用最少时间在表中查找数值为x的元素,若找到,则将其与后继元素位置相交换,若找不到,则将其插入且保持表中元素仍递增有序。
思路:运用折半查找优化时间复杂度。
void FindValue(Sqlist &L, int x) {
int low = 0;
int mid = 0;
int high = L.length - 1;
int temp;
while (low <= high) {
mid = (low + high) / 2;
if (L.data[mid] == x) {
break;
} else if (L.data[mid] > x) {
high = mid - 1;
} else {
low = mid + 1;
}
}
if (L.data[mid] == x && mid != L.length-1) {
temp = L.data[mid];
L.data[mid] = L.data[mid + 1];
L.data[mid + 1] = temp;
}
if (low > high) {
for (int i = L.length - 1; i > high; i--) {
L.data[i + 1] = L.data[i];
}
L.data[low] = x;
L.length++;
}
}
10.设将n(n>1)个整数存放到一维数组R中。设计一个在时间和空间两方面都将可能高效的算法。将R中保存的序列循环左移p(0<p<n)个位置。
思路:把被移部分和剩下部分视为两个数组,实现两个数组整体的逆值即可,即(A1,A2)转变为(A2,A1),其中A1是被移部分的数组,A2是剩下部分的数组。
void reverse3(Sqlist &L, int start, int p) {
int temp = 0;
for (int i = start, k = 0; i < (start + p) / 2 + 1; k++) { //⚠️此处有"+1",假若忽略此条件,当start+p=1时,不会产生互换。
temp = L.data[i];
L.data[i] = L.data[p - k];
L.data[p - k] = temp;
i++;
}
}
void test10() {
int p;
scanf("%d",&p);
Sqlist L = {{1, 2, 3, 4, 5}, 5};
reverse3(L, 0, p-1);
reverse3(L, p, L.length-1);
reverse3(L, 0, L.length-1);
for (int i = 0; i < L.length; i++) {
printf(" %d", L.data[i]);
}
}
11.试设计一个在空间和时间上尽可能高效的算法,找出两个升序序列A和B的中位数。
思路:利用归并算法,合并两个升序序列,并找到新序列的中位数。
double midAB(Sqlist &A, Sqlist &B) {
Sqlist L = {};
int i = 0;
int j = 0;
int k = 0;
double mid = 0;
while (A.length + B.length <= Maxside && i < A.length && j < B.length) {
if (A.data[i] <= B.data[j]) {
L.data[k++] = A.data[i++];
} else {
L.data[k++] = B.data[j++];
}
}
while (i < A.length) {
L.data[k++] = A.data[i++];
}
while (j < B.length) {
L.data[k++] = B.data[j++];
}
L.length = k;
if (k % 2 == 1) { //判断奇数序列
mid = double(L.data[(k + 1) / 2 - 1]);
} else if (k % 2 == 0) { //判断偶数序列
mid = double((L.data[k / 2 - 1] + L.data[k / 2])) / 2;
}
// for (int i = 0; i < L.length; i++) {
// printf(" %d", L.data[i]);
// }
return mid;
}
void test11() {
Sqlist A = {{4, 5, 6}, 3};
Sqlist B = {{1, 2, 3}, 3};
printf(" %0.2f", midAB(A, B));
}
12.请设计一个尽可能高效的算法,找出A的主元素(元素出现次数大于元素总数的一半)。若存在则输出主元素,不存在则输出-1。
int findMainValue(Sqlist &L, int n) {
int *count = (int *) malloc(sizeof(int) * n);
for (int i = 0; i < n; ++i) {
count[i] = 0;//初始化线性表
}
for (int i = 0; i < L.length; i++) {
count[L.data[i]]++;//映射数组,遍历原数组,通过count在新数组的对应位置上统计元素出现次数,此时新数组的索引为原数组的元素值
}
int max = 0, maxIndex = 0;
for (int i = 1; i < n; i++) {
if (count[i] > max) { //找出count值最大(即相同元素出现的最多次数)
max = count[i];
maxIndex = i;
}
}
if (max > L.length / 2) //主元素的判断
return maxIndex;
else
return -1;
}
void test12() {
Sqlist A{{5, 8, 7, 7, 7, 8, 8, 8, 8}, 9};
Sqlist B{{0, 5, 5, 3, 5, 7, 5}, 7};
printf("%d", findMainValue(A, 9));
// findMainValue(B,7);
}
13.给定一个含n(n>=1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小整数。
思路:与上题类似,用映射关系来解决问题。
int Find_NMin_Int(Sqlist &L, int n) { //n>=MaxL.data[i]+2
int mint = 0;
int *count = (int *) malloc(sizeof(int) * n);
for (int i = 0; i < n; ++i) {
count[i] = 0;//初始化线性表
}
for (int i = 0; i < L.length; i++) {
if (L.data[i] < 0) {
L.data[i] == 0; //把L中所有小于0的数改成0
}
count[L.data[i]]++;//映射数组,遍历原数组,通过count在新数组的对应位置上统计元素出现次数,此时新数组的索引为原数组的元素值
}
for (int i = 1; i < n; ++i){
if(count[i]==0){ //找出出现次数为0的最小正整数,并输出。
mint = i;
break;
}
}
return mint;
}
void test13(){
Sqlist L={{-5, 3, 2, 3},4};
Sqlist A={{1, 2, 3},3};
printf("%d", Find_NMin_Int(A,5));
}
14.定义三元组(a,b,c)(a,b,c,均为正数)的距离D = |a-b|+|b-c|+|c-a|。给定3个非空正数集合S1、S2和S3,按升序分别存储在3个数组中。请设计一个尽可能高效的算法,计算并输出所有可能的三元组(a,b,c)的最小距离。
思路:三重for循环找出符合条件的三元组。
#define MAX 0xffffff
int abs(int value) { //构造绝对值函数
if (value < 0)return -value;
else return value;
}
int distance(int i, int j, int k) { //计算距离
int dist = abs(i - j) + abs(j - k) + abs(k - i);
return dist;
}
void Min_distance(Sqlist S1, Sqlist S2, Sqlist S3) {
int min = MAX;
int res[3]; //用于存放三元组
for (int i = 0; i < S1.length; i++) {
for (int j = 0; j < S2.length; j++) {
for (int k = 0; k < S3.length; k++) {
if (min > distance(S1.data[i], S2.data[j], S3.data[k])) {
res[0] = S1.data[i];
res[1] = S2.data[j];
res[2] = S3.data[k];
min = distance(S1.data[i], S2.data[j], S3.data[k]);
}
}
}
}
printf("(%d,%d,%d)", res[0], res[1], res[2]);
}
void test14() {
Sqlist L{{-1, 0, 9}, 3};
Sqlist A{{-25, -10, 10, 11}, 4};
Sqlist B{{2, 9, 17, 30, 41}, 5};
Min_distance(L, A, B);
}