PTA 算法1-3~4 将数组中元素反转存放

算法1-3~4 将数组中元素反转存放

分数 15

作者 陈越

单位 浙江大学

给定 n 个 int 型范围内的整数。请编写程序,将 n 个整数存在数组中,再将这些数组元素反转存放,最后顺序输出反转后数组中的元素。
注:虽然不需要改变数组中元素的位置,也可以按反转的顺序输出,但建议练习者尝试反转数组元素的算法。

输入格式:

输入第一行给出正整数 n(≤104)。第二行给出 n 个 int 型范围内的整数。同行数字间以空格分隔。

输出格式:

在一行中输出反转输入顺序后的结果,每个数字后跟 1 个空格。

输入样例:

1
2
5
1 2 3 4 5

输出样例:

1
5 4 3 2 1 

答案1(静态数组)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<iostream>
using namespace std;

// 反转数组
void reverseArray(int *a, int length) {
int j = length - 1;
for (int i = 0; i < j; i++, j--) {
int temp = a[i]; // 定义一个临时变量
a[i] = a[j];
a[j] = temp;
}
}

int main() {
int n;
cin >> n;
int a[1000];
for (int i = 0; i < n; i++) {
cin >> a[i];
}
reverseArray(a, n);
for (int i = 0; i < n; i++) {
cout << a[i] << " ";
}
}

改进:

  • 使用动态内存分配可以更灵活地管理内存,避免固定大小数组可能带来的空间浪费或溢出风险。结合顺序表(sqList)的思想
  1. 顺序表结构:使用SqList结构体封装了数据指针和长度,更符合数据结构的规范,也方便扩展其他操作(如插入、删除等)。
  2. 动态内存分配
    • 根据输入的n动态分配刚好足够的内存空间,避免固定数组的空间浪费

答案2(顺序表)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include<iostream>
using namespace std;

// 定义顺序表结构:存储元素的数组和当前长度
typedef struct {
int *elem;
int length;
} sqList;

// 初始化顺序表
void InitList(sqList &L, int n) {
L.elem = new int[n];
L.length = 0;
}

// 反转顺序表
void reverseList(sqList &L) {
int j = L.length - 1;
for (int i = 0; i < j; i++, j--) {
int t = L.elem[i];
L.elem[i] = L.elem[j];
L.elem[j] = t;
}
}

void destroyList(sqList &L) {
if (L.elem != nullptr) { // 检查指针有效性
delete[] L.elem; // 使用delete[]释放数组内存
L.elem = nullptr; // 避免野指针
L.length = 0; // 重置长度
}
}

int main() {
int n;
cin >> n; // 读取输入整数的个数n
sqList L;
InitList(L, n); // 初始化顺序表,为顺序表分配空间,令当前长度为0
for (int i = 0; i < n; i++) {
cin >> L.elem[i];
L.length++;
}
reverseList(L);
// 打印反转的顺序表
for (int i = 0; i < L.length; i++) {
cout << L.elem[i] << " ";
}

destroyList(L);
}
  • 注意:
    • 初始化顺序表的时候要为数组开辟一块空间L.elem = new int[n];
    • 要把当前表长置为空L.length = 0;

为什么 destroyList 需要引用传递?

destroyList 的核心功能是:

  • 释放 L.data 指向的动态内存
  • L.data 置为 nullptr(避免野指针)
  • L.length 重置为 0

这些操作都需要修改原始顺序表 L 的成员变量。如果不用引用(即写成 destroyList(SqList L)):

  • 函数会接收 L 的副本(值传递)
  • 释放的是副本中 data 指向的内存(虽然也能释放动态内存,避免泄漏)
  • 但原始 Ldata 仍会指向已释放的内存(变成野指针),length 也不会被重置

这会导致原始顺序表处于无效状态,存在风险。