1. 问题理解
首先,我们需要明确任务是将一个数组中的元素顺序颠倒,即数组的第一个元素变成最后一个,第二个元素变成倒数第二个,依此类推。
2. 解决方案概述
由于数组是连续存储的,我们可以通过交换数组两端对应位置的元素来实现逆序。具体来说,我们可以遍历数组的一半(对于偶数长度的数组)或稍微超过一半(对于奇数长度的数组,但通常我们会停在中间,因为中间的元素在逆序后仍然在其原始位置),并在每次迭代中交换两端的元素。
3. 实现步骤
- 初始化:定义一个临时变量
temp
用于存储交换过程中的元素值。 - 遍历:使用一个循环遍历数组的一半。对于长度为
n
的数组,遍历的索引i
从0
开始,直到size/2 - 1
(包含)。这是因为当我们到达数组的中间时,已经完成了所有必要的交换。 - 交换:在每次迭代中,将
arr[i]
(当前索引处的元素)与arr[size-1-i]
(与当前索引对称位置的元素)的值进行交换。这可以通过将arr[i]
的值存储在temp
中,然后将arr[size-1-i]
的值赋给arr[i]
,最后将temp
中的值赋给arr[size-1-i]
来实现。 - 完成:当遍历完成时,数组中的元素已经被逆序存放。
4. 示例解释
考虑数组arr[] = {1, 2, 3, 4, 5}
,其长度为5。
- 初始时,数组为
{1, 2, 3, 4, 5}
。 - 第一次迭代(
i = 0
),交换arr[0]
(值为1)和arr[4]
(值为5),数组变为{5, 2, 3, 4, 1}
。 - 第二次迭代(
i = 1
),交换arr[1]
(值为2)和arr[3]
(值为4),数组变为{5, 4, 3, 2, 1}
。 - 第三次迭代(
i = 2
),由于数组长度为5(奇数),且我们已经遍历到了中间元素(索引为2的元素),因此不需要再进行交换。但如果数组长度是偶数,比如6,那么还会有一次迭代来交换中间两个对称位置的元素(尽管在这种情况下,这两个元素实际上已经在它们应该在的位置上了)。
5. 代码
#include<stdio.h>
void initArray(int *parr,int size)
{
int i;
for(i=0;i<size;i++){
printf("请输入第%d个数据:",i+1);
scanf("%d",parr++);
}
}
void invertArray(int *parr,int size)
{
int i;
int j;
int temp;
for(i=0;i<size/2;i++){
j = size-1-i;
temp = *(parr+i);
*(parr+i) = *(parr+j);
*(parr+j) = temp;
}
}
void printArray(int *parr,int size)
{
int i;
for(i=0;i<size;i++){
printf("%d ",*parr++);
}
}
int main()
{
int arr[5];
int size = sizeof(arr)/sizeof(arr[0]);
initArray(arr,size);
printArray(arr,size);
putchar('\n');
invertArray(arr,size);
printArray(arr,size);
return 0;
}
输出将是:
请输入第1个数据:99
请输入第2个数据:88
请输入第3个数据:77
请输入第4个数据:66
请输入第5个数据:55
99 88 77 66 55
55 66 77 88 99
6. 效率和适用性
这种方法的时间复杂度是O(n/2),其中n是数组的长度。由于常数因子在渐进分析中被忽略,因此可以简化为O(n)。这种方法适用于任何长度的数组,并且不需要额外的存储空间(除了用于交换的临时变量)。因此,它是原地(in-place)且高效的。