#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
参数,意图是通过引用传递数组。但是,这种写法是不合法的。数组本身不能作为引用类型,因为数组类型的引用是有特殊语法要求的。
正确的写法
如果你希望通过引用修改数组的内容,可以使用以下几种方式:
-
通过指针传递数组(常见做法): 数组在函数传递时本质上是作为指针传递的。你传入数组时,实际上是传递了数组的首地址(即指向数组第一个元素的指针)。因此,使用指针参数是处理数组的标准做法。
void bubbleSort(int* arr, int len)
在这种情况下,
arr
是一个指向整数的指针,指向数组的第一个元素。你可以通过指针修改数组中的元素。 -
使用
std::array
或std::vector
: 如果你使用 标准容器(如std::array
或std::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]); } } } }
-
数组引用(较少使用): 如果你确实需要通过引用来传递数组(并且数组大小固定),可以使用以下语法:
void bubbleSort(int (&arr)[10], int len) { // arr 是一个引用,表示一个固定大小的数组 }
这种方式只有在数组大小已知且固定的情况下才适用(如
arr[10]
)。这样你可以确保传入的是一个固定大小的数组,并且可以通过引用修改数组。
为什么 int & arr[]
不行
-
数组引用语法错误:C++ 中,数组引用的正确写法应该是
int (&arr)[size]
,即必须指定数组的大小。因此,int& arr[]
是非法的。 -
数组和指针的区别:数组本身是一个固定的大小,引用(
&
)通常用来绑定某个对象(如变量、类对象等),而数组传递时,实际上传递的是数组的地址,因此我们通常使用指针而非引用来传递数组。
代码修正
因此,如果你要按原来的思路使用 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]
- 比较