C语言数组与指针实战:原地倒序数组元素(课后作业详解)


🎯 题目要求

编写一个函数 f(int a[]),该函数接收一个有序数组,并将其元素原地倒序存储 —— 即第一个元素与最后一个交换,第二个与倒数第二个交换,以此类推。

main() 函数中:

  • 定义数组 int b[5] = {1, 2, 3, 4, 5};
  • 调用函数 f(b);
  • 输出倒序后的数组内容

⚠️ 关键限制:函数中不允许定义额外数组,必须在原数组内完成倒序操作


💡 解题思路

这是一个经典的“双指针原地交换”问题:

  1. 设置两个指针(或索引):
    • left 从数组开头(索引 0)开始
    • right 从数组末尾(索引 len-1)开始
  2. 交换 a[left]a[right]
  3. left++, right--
  4. 重复直到 left >= right

这样可以在 O(n/2) 时间内完成倒序,空间复杂度为 O(1),完美符合“原地操作”要求。


✅ 完整代码实现

#include <stdio.h>

// 函数声明:原地倒序数组
void f(int a[], int len);

int main() {
    // 定义并初始化数组
    int b[5] = {1, 2, 3, 4, 5};
    int i;

    printf("原数组: ");
    for (i = 0; i < 5; i++) {
        printf("%d ", b[i]);
    }
    printf("\n");

    // 调用函数倒序
    f(b, 5);

    printf("倒序后: ");
    for (i = 0; i < 5; i++) {
        printf("%d ", b[i]);
    }
    printf("\n");

    return 0;
}

// 函数定义:原地倒序数组元素
void f(int a[], int len) {
    int left = 0;
    int right = len - 1;
    int temp;

    // 双指针交换直到相遇
    while (left < right) {
        // 交换元素
        temp = a[left];
        a[left] = a[right];
        a[right] = temp;

        // 移动指针
        left++;
        right--;
    }
}

🧪 运行结果

原数组: 1 2 3 4 5 
倒序后: 5 4 3 2 1 

✅ 完全符合题目要求!


🧠 知识点解析

1. 数组作为函数参数的本质是“指针”

在 C 语言中,void f(int a[])void f(int *a) 是等价的 —— 数组名在传参时退化为指向首元素的指针。因此,函数内部对 a[] 的修改会直接影响原数组 b

2. 原地操作(In-place Algorithm)

  • 优点:节省内存,无需额外空间。
  • 核心思想:利用变量交换 + 双指针技巧。
  • 适用场景:数组翻转、字符串逆序、部分排序等。

3. 边界控制

循环条件 while (left < right) 确保:

  • 偶数长度数组:指针在中间“擦肩而过”
  • 奇数长度数组:指针在正中间元素“相遇”停止
    → 中间元素无需交换,位置不变。

🚀 扩展思考

你可以尝试以下变体练习:

  1. 使用递归实现倒序
  2. 不使用临时变量交换(异或技巧)
    a[left] ^= a[right];
    a[right] ^= a[left];
    a[left] ^= a[right];
    
  3. 倒序字符串
  4. 倒序二维数组的每一行

📌 总结

本题虽然简单,但涵盖了 C 语言中几个核心概念:

  • ✅ 数组与指针的等价性
  • ✅ 函数传参的“地址传递”特性
  • ✅ 双指针算法思想
  • ✅ 原地操作的内存效率

掌握这类基础题型,对后续学习数据结构(如链表反转、栈操作等)大有裨益!


💬 互动提问:你还能想到哪些“原地操作”的经典算法?欢迎在评论区分享交流!

📌 收藏 + 关注,持续更新 C 语言、数据结构与算法实战内容!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值