c++基础知识

#include<iostream>
using namespace std;
//冒泡排序函数 参数1 数组的首地址 参数2 数组长度
void bubbleSort(int  arr[], int len) {//将指针传入后可以修改值,也可以是*arr
	for (int i = 0; i < len-1; i++){
		for (int j = 0; j < len-i-1; j++){
			//如果j>j+1的值,就交换数字
			if (arr[j] > arr[j + 1]){
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}
//打印数组
void printArray(int  arr[], int len) {
	for (int i = 0; i < len; i++){
		cout << arr[i] << " ";
	}
	cout << endl;
}
int main(){
	//1.先创建数组
	int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
	int len = sizeof(arr) / sizeof(arr[0]);
	//2.创建函数,实现冒泡排序
	bubbleSort(arr, len);
	//3.打印排序后的序列
	printArray(arr, len);
	system("pause");
	return 0;
}

在 C++ 中,int& arr[] 这种写法是错误的,原因是 数组引用 的语法不正确。让我来详细解释一下:

错误的地方

void bubbleSort(int & arr[], int len)

在这里,你尝试使用 int & arr[] 来声明 arr 参数,意图是通过引用传递数组。但是,这种写法是不合法的。数组本身不能作为引用类型,因为数组类型的引用是有特殊语法要求的。

正确的写法

如果你希望通过引用修改数组的内容,可以使用以下几种方式:

  1. 通过指针传递数组(常见做法): 数组在函数传递时本质上是作为指针传递的。你传入数组时,实际上是传递了数组的首地址(即指向数组第一个元素的指针)。因此,使用指针参数是处理数组的标准做法。

    void bubbleSort(int* arr, int len)
    

    在这种情况下,arr 是一个指向整数的指针,指向数组的第一个元素。你可以通过指针修改数组中的元素。

  2. 使用 std::arraystd::vector: 如果你使用 标准容器(如 std::arraystd::vector),你可以通过引用传递整个容器,而不需要手动处理指针。

    例如,使用 std::vector 作为参数,既可以通过引用修改容器,又能保证数组大小的灵活性:

    void bubbleSort(std::vector<int>& arr) {
        int len = arr.size();
        for (int i = 0; i < len-1; i++) {
            for (int j = 0; j < len-i-1; j++) {
                if (arr[j] > arr[j + 1]) {
                    std::swap(arr[j], arr[j + 1]);
                }
            }
        }
    }
    
  3. 数组引用(较少使用): 如果你确实需要通过引用来传递数组(并且数组大小固定),可以使用以下语法:

    void bubbleSort(int (&arr)[10], int len) {
        // arr 是一个引用,表示一个固定大小的数组
    }
    

    这种方式只有在数组大小已知且固定的情况下才适用(如 arr[10])。这样你可以确保传入的是一个固定大小的数组,并且可以通过引用修改数组。

为什么 int & arr[] 不行

  1. 数组引用语法错误:C++ 中,数组引用的正确写法应该是 int (&arr)[size],即必须指定数组的大小。因此,int& arr[] 是非法的。

  2. 数组和指针的区别:数组本身是一个固定的大小,引用(&)通常用来绑定某个对象(如变量、类对象等),而数组传递时,实际上传递的是数组的地址,因此我们通常使用指针而非引用来传递数组。

代码修正

因此,如果你要按原来的思路使用 int* 传递数组,正确的 bubbleSort 函数应该是:

void bubbleSort(int* arr, int len) {
    for (int i = 0; i < len-1; i++) {
        for (int j = 0; j < len-i-1; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

并且在 main 函数中传入数组时,arr 作为指针传递:

int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
int len = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr, len);

总结

举个例子

假设我们有一个数组:

int arr[10] = {4, 3, 6, 9, 1, 2, 10, 8, 7, 5};
外层循环 1(i = 0)

经过这一轮遍历,最大元素 10 被“冒泡”到了最后。

外层循环 2(i = 1)

最大值 9 被“冒泡”到了倒数第二位。

结论

每次外层循环结束时,未排序部分的最大值会被“冒泡”到数组的末尾。因此,内层循环需要从 数组的起始位置j = 0)开始,逐步将未排序部分的元素进行比较和交换,确保最大的元素被“冒泡”到正确的位置。

  • 你不能写 int & arr[],因为数组的引用语法不允许这么写。
  • 要传递数组,你可以使用 指针 int* arr 或者使用 标准容器(如 std::vector<int>)。
  • 如果你想通过引用修改数组,可以使用 int (&arr)[size](适用于固定大小的数组)。
  • 好的问题!这个逻辑正是冒泡排序的核心之一。让我们详细分析一下为什么在每次外层循环时,内层循环从 j = 0 开始遍历。

    冒泡排序的原理回顾

    冒泡排序的核心思想是通过每一轮外层循环,把当前未排序部分的最大值“冒泡”到数组的末尾。为了实现这一目标,每次内层循环都要比较数组相邻的元素,并将不符合顺序的元素交换位置。

    关键点:内层循环的执行

    for (int j = 0; j < len - i - 1; j++)
    

    这里的内层循环从 j = 0 开始,目的是 重新遍历从数组头开始的每一对相邻元素,直到将当前未排序部分的最大值移动到合适的位置。

    为什么内层循环每次都从 j = 0 开始?

  • 外层循环控制每一趟排序的次数: 外层循环变量 i 表示已经排序好的元素个数。每次外层循环结束,数组的最后一个位置都应该是当前未排序部分的最大值。由于 数组的大小不断缩小,每次内层循环的有效范围就减少。

    • i = 0 时,数组的所有元素都需要比较。
    • i = 1 时,已将最大值排到了末尾,因此内层循环只需要比较剩余部分的元素。
    • i = 2 时,最大的两个元素已经排好,内层循环只比较剩余的部分。
  • 每次内层循环都从头开始,保证冒泡过程: 在每一轮外层循环中,最大的未排序元素会被移动到数组的末尾。而为了确保比较的是当前未排序部分的相邻元素,内层循环必须从数组的 起始位置 开始,逐步向后移动,直到当前位置是当前未排序部分的最后一个元素。

  • 交换过程: 每一趟内层循环都会比较 相邻的元素(即 arr[j]arr[j + 1]),如果它们顺序错误,就交换它们的位置。这样,较大的元素逐渐“冒泡”到数组的末尾。

  • 初始数组:[4, 3, 6, 9, 1, 2, 10, 8, 7, 5]
  • 内层循环从 j = 0 开始:
    • 比较 arr[0]arr[1],交换它们:[3, 4, 6, 9, 1, 2, 10, 8, 7, 5]
    • 比较 arr[1]arr[2],不交换:[3, 4, 6, 9, 1, 2, 10, 8, 7, 5]
    • 比较 arr[2]arr[3],不交换:[3, 4, 6, 9, 1, 2, 10, 8, 7, 5]
    • 比较 arr[3]arr[4],交换它们:[3, 4, 6, 1, 9, 2, 10, 8, 7, 5]
    • 比较 arr[4]arr[5],交换它们:[3, 4, 6, 1, 2, 9, 10, 8, 7, 5]
    • 比较 arr[5]arr[6],不交换:[3, 4, 6, 1, 2, 9, 10, 8, 7, 5]
    • 比较 arr[6]arr[7],交换它们:[3, 4, 6, 1, 2, 9, 8, 10, 7, 5]
    • 比较 arr[7]arr[8],交换它们:[3, 4, 6, 1, 2, 9, 8, 7, 10, 5]
    • 比较 arr[8]arr[9],交换它们:[3, 4, 6, 1, 2, 9, 8, 7, 5, 10]
  • 当前数组:[3, 4, 6, 1, 2, 9, 8, 7, 5, 10]
  • 内层循环从 j = 0 开始:
    • 比较 arr[0]arr[1],不交换:[3, 4, 6, 1, 2, 9, 8, 7, 5, 10]
    • 比较 arr[1]arr[2],不交换:[3, 4, 6, 1, 2, 9, 8, 7, 5, 10]
    • 比较 arr[2]arr[3],交换它们:[3, 4, 1, 6, 2, 9, 8, 7, 5, 10]
    • 比较 arr[3]arr[4],交换它们:[3, 4, 1, 2, 6, 9, 8, 7, 5, 10]
    • 比较 arr[4]arr[5],不交换:[3, 4, 1, 2, 6, 9, 8, 7, 5, 10]
    • 比较 arr[5]arr[6],交换它们:[3, 4, 1, 2, 6, 8, 9, 7, 5, 10]
    • 比较 arr[6]arr[7],交换它们:[3, 4, 1, 2, 6, 8, 7, 9, 5, 10]
    • 比较 arr[7]arr[8],交换它们:[3, 4, 1, 2, 6, 8, 7, 5, 9, 10]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值