PTA 6-3 动态输入排序 题解

原题

本题要求实现一个函数input,能够输入n个整数。

裁判测试程序样例:

点击查看代码
/* 请在这里填写答案 */
//实现input函数

void sort(int a[], int n){
    int i,j;
    for(i=0;i<n-1;i++){
        int min = i;
        for(j=i+1;j<n;j++){
            if(a[min]>a[j]) min = j; 
        }
        int t = a[i]; a[i] = a[min]; a[min] = t;
    }
}

int main(){
    int *a;
    int n; 
    cin>>n;                //输入数据的数量 
    input(a,n);            //输入n个整数 
    sort(a,n);            //将数组a按从小到大排序
    for(int i=0;i<n;i++) 
        cout<<a[i]<<" "; //按顺序输出
    
    if(a!=NULL)
        delete []a; 
    return 0;    
}

输入样例:

在这里给出一组输入。例如:

5
10 9 8 7 6

输出样例:

在这里给出相应的输出。例如:

6 7 8 9 10 4

解析

要注意,标准代码中没有为 a 分配内存,我们要自己分配。
但若只在 input() 函数中加入一句 a = new int [n]; 是会报错的,我们在应该把函数也改写为 input(int *&a, int n)
因为 int a, int *a, int *&a是不一样的,我们这里要在函数内直接修改外部指针

这个问题涉及C++中符号的语义差异,用具体例子说明:

三种参数传递方式对比:

int a(值传递):

void func(int a) {
    a = 10; // 仅修改局部副本
}

int main() {
    int x = 5;
    func(x);  // x仍为5
}

int* a(指针传递):

void func(int* a) {
    *a = 10;  // 修改指向的内容 ✔️
    a = new int(20); // 仅修改指针副本 ❌
}

int main() {
    int x = 5;
    int* p = &x;
    func(p);  // x变为10,但p仍指向x
}

int* &a(指针的引用传递):

void func(int* &a) {
    a = new int(20); // 直接修改外部指针 ✔️
}

int main() {
    int* p = nullptr;
    func(p);  // p现在指向新分配的int(20)
}

为什么需要 int* &a

当需要让函数修改外部指针本身(比如在input()中分配内存)普通指针参数 int* a只能修改指针指向的内容,无法改变指针的指向地址.
引用传递&让参数成为原指针的别名.
符号的语法本质:

int* &a  // 读作:a是对int指针的引用
         // 与运算符无关,这里没有使用*和&的运算符
         // 这是类型声明中的组合符号

这就是为什么在需要修改指针本身时,必须使用指针的引用参数。
与之对比,sort(int a[], int n) 函数就不需要头疼这个问题,这是因为 sort() 函数只对指针指向的内存地址做修改,而不改变指针本身。

于是正确代码:

void input(int *&a, int n){
    a = new int[n];
    for(int i=0; i<n; i++){
        cin >> a[i];
    }
}

其他探讨

回顾一下基本的指针,&是取地址符
这里的指针可以修改指向内容,但不能修改指针本身,如果修改,将仅影响函数内的局部指针副本,如 x = new int[10]

其中图中的数组传递时会退化为一个指向数组首字母的指针。

但是指针和引用应该分开看,,这两个东西是不同的

// 引用版本(本题解法)
void mySwap(int &x, int &y) { ... }
mySwap(a, b);  // 直接传变量
// 参数声明中的 & 是引用声明符(不是取地址运算符) 表示x和y是调用时传入变量的别名

// 指针版本(需要改变调用方式)
void mySwap(int* x, int* y) { ... }
mySwap(&a, &b); // 必须传地址
posted @ 2025-04-30 14:53  [丘李]Chilllee  阅读(11)  评论(0)    收藏  举报