二、综合应用题
————————————————————
————————————————————
算法思想:搜索整个顺序表,查找最小值元素并记住其位置,搜索结束后用最后一个元素填补空出的原最小值元素的位置。
#define _CRT_SECURE_NO_WARNINGS//禁用安全函数警告
#pragma warning(disable:6031)//禁用 6031 的安全警告
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
using namespace std;
typedef int ElemType;
#define MaxSize 6 //定义线性表的最大长度为6
typedef struct {
ElemType data[MaxSize];
int length;
}SqList;
bool Del_Min(SqList &L, ElemType &value) {
if (L.length == 0)
return false;
value = L.data[0];
int pos = 0;
for (int i = 1; i < L.length; i++) {
if (L.data[i] < value) {
value = L.data[i];
pos = i;
}
}
L.data[pos] = L.data[L.length - 1];
L.length--;
return true;
}
int main() {
SqList L;
int value;
L.length = 0;
printf("请依次输入顺序表的所有值:");
for (int i = 0; i < MaxSize; i++) {
scanf("%d", &L.data[i]);
L.length++; //每输入一个数顺序表的当前长度加1
}
printf("原顺序表为:");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
Del_Min(L, value);
printf("使用函数后的顺序表为:");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
return 0;
}
运行结果:
————————————————————
————————————————————
算法思想:扫描顺序表L的前半部分元素,对于元素工.data[i](0<=i<L.length/2),将其与后半部分的对应元素L.data[L.length-i-1]进行交换。
#define _CRT_SECURE_NO_WARNINGS//禁用安全函数警告
#pragma warning(disable:6031)//禁用 6031 的安全警告
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int ElemType;
#define MaxSize 6 //定义线性表的最大长度为6
typedef struct {
ElemType data[MaxSize];
int length;
}SqList;
void Reverse(SqList& L) {
ElemType temp;
for (int i = 0; i < L.length / 2; i++) {
temp = L.data[i];
L.data[i] = L.data[L.length - 1 - i];
L.data[L.length - 1 - i] = temp;
}
}
int main() {
SqList L;
L.length = 0;
printf("请依次输入顺序表的所有值:");
for (int i = 0; i < MaxSize; i++) {
scanf("%d", &L.data[i]);
L.length++; //每输入一个数顺序表的当前长度加1
}
printf("原顺序表为:");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
Reverse(L);
printf("使用逆置函数后的顺序表为:");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
return 0;
}
运行结果:
————————————————————
————————————————————
算法思想:设一个变量k,初始值为0,扫描时将不等于x的元素移到下标为k的位置,并更新k值。最后需要修改L的长度。
#define _CRT_SECURE_NO_WARNINGS//禁用安全函数警告
#pragma warning(disable:6031)//禁用 6031 的安全警告
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int ElemType;
#define MaxSize 6 //定义线性表的最大长度为6
typedef struct {
ElemType data[MaxSize];
int length;
}SqList;
void Del_x(SqList& L, ElemType x) {
ElemType k = 0;
for (int i = 0; i < L.length; i++) {
if (L.data[i] != x) {
L.data[k] = L.data[i];
k++;
}
}
L.length = k;
}
int main() {
SqList L;
L.length = 0;
printf("请依次输入顺序表的所有值: ");
for (int i = 0; i < MaxSize; i++) {
scanf("%d", &L.data[i]);
L.length++; //每输入一个数顺序表的当前长度加1
}
printf("原顺序表为: ");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
ElemType x;
printf("请输入需要删除的元素x: ");
scanf("%d", &x);
Del_x(L, x);
printf("使用函数后的顺序表为:");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
return 0;
}
运行结果:
————————————————————
————————————————————
算法思想:从前向后扫描顺序表L,用k记录值在s和t之间的元素个数(初始时k=0)。对于当前扫描的元素,若其值不在s和 t之间,则前移k个位置;否则执行k++。由于每个不在s和t之间的元素仅移动一次,因此算法效率高。
#define _CRT_SECURE_NO_WARNINGS//禁用安全函数警告
#pragma warning(disable:6031)//禁用 6031 的安全警告
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int ElemType;
#define MaxSize 6 //定义线性表的最大长度为6
typedef struct {
ElemType data[MaxSize];
int length;
}SqList;
bool Del_s_t(SqList& L, ElemType s, ElemType t) {
ElemType k = 0;
if (L.length == 0 || s >= t) {
return false;
}
for (int 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 -= k;
return true;
}
int main() {
SqList L;
L.length = 0;
printf("请依次输入顺序表的所有值: ");
for (int i = 0; i < MaxSize; i++) {
scanf("%d", &L.data[i]);
L.length++; //每输入一个数顺序表的当前长度加1
}
printf("原顺序表为: ");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
ElemType s, t;
printf("请输入s和t: ");
scanf("%d%d", &s, &t);
Del_s_t(L, s, t);
printf("使用函数后的顺序表为:");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
return 0;
}
运行结果:
————————————————————
————————————————————
算法思想:注意是有序顺序表,值相同的元素一定在连续的位置上,用类似于直接插入排序的思想,初始时将第一个元素视为非重复的有序表。之后依次判断后面的元素是否与前面非重复有序表的最后一个元素相同,若相同,则继续向后判断,若不同,则插入前面的非重复有序表的最后,直至判断到表尾为止。
#define _CRT_SECURE_NO_WARNINGS//禁用安全函数警告
#pragma warning(disable:6031)//禁用 6031 的安全警告
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int ElemType;
#define MaxSize 6 //定义线性表的最大长度为6
typedef struct {
ElemType data[MaxSize];
int length;
}SeqList;
bool Del_Same(SeqList& L) {
if (L.length == 0)
return false;
int 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;
}
int main() {
SeqList L;
L.length = 0;
printf("请依次输入顺序表的所有值: ");
for (int i = 0; i < MaxSize; i++) {
scanf("%d", &L.data[i]);
L.length++; //每输入一个数顺序表的当前长度加1
}
printf("原顺序表为: ");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
Del_Same(L);
printf("使用函数后的顺序表为:");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
return 0;
}
运行结果:
————————————————————
————————————————————
算法思想:首先,按顺序不断取下两个顺序表表头较小的结点存入新的顺序表中。然后,看哪个表还有剩余,将剩下的部分加到新的顺序表后面。
#define _CRT_SECURE_NO_WARNINGS//禁用安全函数警告
#pragma warning(disable:6031)//禁用 6031 的安全警告
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int ElemType;
#define MaxSize 10
typedef struct {
ElemType data[MaxSize];
int length;
}SeqList;
bool Merge(SeqList A, SeqList B, SeqList &C) {
//将有顺序的顺序表A,B合并到新的有序顺序表C中
if (A.length + B.length > 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[j++];
C.length = k;
return true;
}
int main() {
SeqList A, B, C;
A.length = 0;
B.length = 0;
C.length = 0;
int i;
char s;
i = 0;
printf("请依次输入A顺序表的所有值: ");
for (int i = 0; i < MaxSize; i++) {
scanf("%d", &A.data[i]);
A.length++;
s = getchar();
if (s == '\n')
break;
}
i = 0;
printf("请依次输入B顺序表的所有值: ");
for (int i = 0; i < MaxSize; i++) {
scanf("%d", &B.data[i]);
B.length++;
s = getchar();
if (s == '\n')
break;
}
printf("原顺序表A为: ");
for (int i = 0; i < A.length; i++) {
printf("%d ", A.data[i]);
}
printf("\n");
printf("原顺序表B为: ");
for (int i = 0; i < B.length; i++) {
printf("%d ", B.data[i]);
}
printf("\n");
Merge(A, B, C);
printf("使用函数后的顺序表C为:");
for (int i = 0; i < C.length; i++) {
printf("%d ", C.data[i]);
}
return 0;
}
运行结果:
————————————————————
————————————————————
算法思想:首先将数组A[m +n]中的全部元素(a1, a2, a3,… , am, b1, b2, b3,…. bn)原地逆置为(bn, bn-1, bn-2,…, b1, am, am-1, am-2,…, a1),然后对前n个元素和后m个元素分别使用逆置算法,即可得到(b,1 b2, b3,…, bn, a1, a2, a3,…, am),从而实现顺序表的位置互换。
#define _CRT_SECURE_NO_WARNINGS//禁用安全函数警告
#pragma warning(disable:6031)//禁用 6031 的安全警告
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int ElemType;
typedef int DataType;
#define MaxSize 10
typedef struct {
ElemType data[MaxSize];
int length;
}SeqList;
void Reverse(DataType A[], int left, int right, int arraySize) { //起始位置left和终止位置right
DataType temp; //中间变量
if (left >= right || right >= arraySize) {
return; //void类型的函数直接return
}
int mid = (left + right) / 2;
for (int i = 0; i <= mid - left; i++) {
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);
}
int main() {
DataType A[MaxSize] = {0};
int m = 4;
int n = 6;
printf("请依次输入顺序表的所有值: ");
for (int i = 0; i < MaxSize; i++) {
scanf("%d", &A[i]);
}
printf("原顺序表为: ");
for (int i = 0; i < MaxSize; i++) {
printf("%d ", A[i]);
}
printf("\n");
Exchange(A, m, n, MaxSize);
printf("使用函数后的顺序表为:");
for (int i = 0; i < MaxSize; i++) {
printf("%d ", A[i]);
}
return 0;
}
运行结果:
————————————————————
————————————————————
#define _CRT_SECURE_NO_WARNINGS//禁用安全函数警告
#pragma warning(disable:6031)//禁用 6031 的安全警告
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int ElemType;
typedef int DataType;
#define MaxSize 6
typedef struct {
ElemType data[MaxSize];
int length;
}SeqList;
void SearchExchangeInsert(ElemType A[], ElemType x, int n) {
int low = 0, high = n - 1;
int mid; //low和high指向顺序表下界和上界的下标
while (low <= high) {
mid = (low + high) / 2; //找中间位置
if (A[mid] == x) break; //找到x
else if (A[mid] < x) low = mid + 1; //到中点mid的右半部去查
else high = mid - 1; //到中点mid的左半部去查
} //下面两个if语句只会执行一个
if (A[mid] == x && mid != n - 1) { //若最后一个元素与x相等,则不存在与其后继交换的操作
int t = A[mid]; A[mid] = A[mid + 1]; A[mid + 1] = t;
}
if (low > high) { //查找失败,插入数据元素X
int i;
for (i = n - 1; i > high; i--) A[i + 1] = A[i]; //后移元素
A[i + 1] = x; //插入X
} //插入结束
}
int main() {
ElemType A[MaxSize] = { 0 };
int x;
printf("请依次输入顺序表的所有值: ");
for (int i = 0; i < MaxSize; i++) {
scanf("%d", &A[i]);
}
printf("请输入要查找的值: ");
scanf("%d", &x);
printf("原顺序表为: ");
for (int i = 0; i < MaxSize; i++) {
printf("%d ", A[i]);
}
printf("\n");
SearchExchangeInsert(A, x, MaxSize);
printf("使用函数后的顺序表为:");
for (int i = 0; i < MaxSize; i++) {
printf("%d ", A[i]);
}
return 0;
}
运行效果:
————————————————————
————————————————————
解答:
(1)使用三个下标变量从小到大遍历数组。当三个下标变量指向的元素相等时,输出并向前推进指针,否则仅移动小于最大元素的下标变量,直到某个下标变量移出数组范围,即可停止。
(2)
#define _CRT_SECURE_NO_WARNINGS//禁用安全函数警告
#pragma warning(disable:6031)//禁用 6031 的安全警告
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <algorithm>
using namespace std;
typedef int ElemType;
#define MaxSize 3
typedef struct {
ElemType data[MaxSize];
int length;
}SeqList;
void samekey(int A[], int B[], int C[], int n) {
int i = 0, j = 0, k = 0; //定义三个工作指针
while (i < n && j < n && k < n) { //相同则输出,并集体后移
if (A[i] == B[j] && B[j] == C[k]) {
printf("%d\n", A[i]);
i++; j++; k++;
}
else {
int maxNum = max(A[i], max(B[j], C[k]));
if (A[i] < maxNum) i++;
if (B[i] < maxNum) j++;
if (C[i] < maxNum) k++;
}
}
}
int main() {
ElemType A[MaxSize] = { 0 };
ElemType B[MaxSize] = { 0 };
ElemType C[MaxSize] = { 0 };
printf("请依次输入A顺序表的所有值: ");
for (int i = 0; i < MaxSize; i++) {
scanf("%d", &A[i]);
}
printf("请依次输入B顺序表的所有值: ");
for (int i = 0; i < MaxSize; i++) {
scanf("%d", &B[i]);
}
printf("请依次输入C顺序表的所有值: ");
for (int i = 0; i < MaxSize; i++) {
scanf("%d", &C[i]);
}
printf("原顺序表为: ");
for (int i = 0; i < MaxSize; i++) {
printf("%d ", A[i]);
}
printf("\n");
for (int i = 0; i < MaxSize; i++) {
printf("%d ", B[i]);
}
printf("\n");
for (int i = 0; i < MaxSize; i++) {
printf("%d ", C[i]);
}
printf("\n");
printf("重复的元素为:");
samekey(A, B, C, MaxSize);
return 0;
}
运行结果:
(3)
每个指针移动的次数不超过n次,且每次循环至少有一个指针后移,所以时间复杂度为O(n),算法只用到了常数个变量,空间复杂度为O(1)。
————————————————————
————————————————————
解答:
————————————————————
————————————————————
解答:
————————————————————
————————————————————
解答:
————————————————————
————————————————————
解答:
————————————————————
————————————————————
解答: