欢迎光临
我们一直在努力

冒泡排序与数组传递全解析 一维二维指针数组及二级指针应用指南

冒泡排序与数组传递全解析 一维二维指针数组及二级指针传参指南

一、冒泡排序核心知识点

冒泡排序是一种简单的交换排序算法,核心思想是通过相邻元素的比较与交换,让较大(或较小)的元素像气泡一样逐步“浮”到数组末端。以升序排序为例,步骤如下:

  • 比较相邻元素:从数组第一个元素开始,依次比较相邻的两个元素(如arr[i]和arr[i+1])。

  • 交换逆序元素:如果前一个元素大于后一个元素(arr[i] > arr[i+1]),则交换它们的位置。

  • 重复多轮:每一轮排序后,最大的元素会“沉”到当前未排序部分的末尾。因此,若有n个元素,需进行n-1轮排序(最后一个元素无需再比较)。

  • 优化:若某一轮未发生交换,说明数组已有序,可提前结束排序。

  • 二、传递一维数组给冒泡排序函数
    知识点

    C语言中,数组作为函数参数时会退化为指针,因此传递一维数组时需同时传递数组长度(编译器无法通过数组名获取长度)。函数参数可写为int arr[](等价于int *arr),接收数组首地址。

    示例代码(含注释)

    #include <stdio.h>

    // 冒泡排序函数:对一维数组升序排序
    // 参数:arr 数组首地址(退化为指针),len 数组长度
    void bubble_sort_1d(int arr[], int len) {
    int i, j, temp;
    int swapped; // 标记本轮是否发生交换,用于优化
    for (i = 0; i < len – 1; i++) { // 共需 len-1 轮排序
    swapped = 0; // 初始化为未交换
    // 每轮比较次数:未排序部分长度为 len – i,需比较 len – i – 1 次
    for (j = 0; j < len – i – 1; j++) {
    if (arr[j] > arr[j + 1]) { // 前大后小,交换
    temp = arr[j];
    arr[j] = arr[j + 1];
    arr[j + 1] = temp;
    swapped = 1; // 标记发生交换
    }
    }
    if (!swapped) break; // 本轮无交换,数组已有序,提前退出
    }
    }

    // 打印数组
    void print_array(int arr[], int len) {
    int i;
    for (i = 0; i < len; i++) {
    printf("%d ", arr[i]);
    }
    printf("\\n");
    }

    int main() {
    int nums[] = {64, 34, 25, 12, 22, 11, 90};
    int len = sizeof(nums) / sizeof(nums[0]); // 计算数组长度

    printf("排序前数组:");
    print_array(nums, len);

    bubble_sort_1d(nums, len); // 传递一维数组和长度

    printf("排序后数组:");
    print_array(nums, len);
    return 0;
    }

    三、传递二维数组给冒泡排序函数
    知识点

    二维数组传递需注意函数参数必须指定第二维的大小(除非用指针数组或数组指针)。可将二维数组视为“一维数组”(内存连续),对所有元素统一排序。

    示例代码(含注释)

    #include <stdio.h>

    // 冒泡排序二维数组(整体排序,视为一维数组)
    // 参数:arr 二维数组首地址(第二维固定为4),rows 行数,cols 列数
    void bubble_sort_2d(int arr[][4], int rows, int cols) {
    int total = rows * cols; // 总元素个数
    int i, j, temp;
    int swapped;

    for (i = 0; i < total – 1; i++) {
    swapped = 0;
    for (j = 0; j < total – i – 1; j++) {
    // 计算当前元素的行列坐标(模拟一维索引转二维)
    int row1 = j / cols, col1 = j % cols;
    int row2 = (j + 1) / cols, col2 = (j + 1) % cols;

    if (arr[row1][col1] > arr[row2][col2]) {
    temp = arr[row1][col1];
    arr[row1][col1] = arr[row2][col2];
    arr[row2][col2] = temp;
    swapped = 1;
    }
    }
    if (!swapped) break;
    }
    }

    // 打印二维数组
    void print_2d_array(int arr[][4], int rows, int cols) {
    int i, j;
    for (i = 0; i < rows; i++) {
    for (j = 0; j < cols; j++) {
    printf("%d ", arr[i][j]);
    }
    printf("\\n");
    }
    }

    int main() {
    int matrix[3][4] = {{9, 5, 7, 3}, {2, 8, 1, 6}, {4, 0, 10, 12}};
    int rows = 3, cols = 4;

    printf("排序前二维数组:\\n");
    print_2d_array(matrix, rows, cols);

    bubble_sort_2d(matrix, rows, cols);

    printf("排序后二维数组(整体升序):\\n");
    print_2d_array(matrix, rows, cols);
    return 0;
    }

    四、指针数组与冒泡排序
    知识点

    指针数组是数组元素为指针变量的数组(如char *str_arr[])。对指针数组排序时,交换指针(而非内容)更高效,常用于字符串排序(按字典序)。指针数组名退化为二级指针(char **)。

    示例代码(含注释)

    #include <stdio.h>
    #include <string.h>

    // 冒泡排序指针数组(交换指针,按字符串字典序升序)
    // 参数:str_arr 指针数组首地址(等价于二级指针 char **),len 数组长度
    void bubble_sort_str_ptr(char *str_arr[], int len) {
    int i, j;
    char *temp; // 临时指针(交换指针用)
    int swapped;

    for (i = 0; i < len – 1; i++) {
    swapped = 0;
    for (j = 0; j < len – i – 1; j++) {
    // strcmp比较字符串:返回正数表示前者大于后者
    if (strcmp(str_arr[j], str_arr[j + 1]) > 0) {
    temp = str_arr[j]; // 交换指针(核心)
    str_arr[j] = str_arr[j + 1];
    str_arr[j + 1] = temp;
    swapped = 1;
    }
    }
    if (!swapped) break;
    }
    }

    // 打印字符串数组
    void print_str_array(char *str_arr[], int len) {
    int i;
    for (i = 0; i < len; i++) {
    printf("%s ", str_arr[i]);
    }
    printf("\\n");
    }

    int main() {
    char *fruits[] = {"banana", "apple", "cherry", "date"}; // 指针数组
    int len = sizeof(fruits) / sizeof(fruits[0]);

    printf("排序前字符串数组:");
    print_str_array(fruits, len);

    bubble_sort_str_ptr(fruits, len); // 传递指针数组(退化为二级指针)

    printf("排序后字符串数组(字典序升序):");
    print_str_array(fruits, len);
    return 0;
    }

    五、二级指针传参与冒泡排序
    知识点

    二级指针(如int **pp)是指向指针的指针,用于存储“指针变量的地址”。在数组传递中,二级指针主要用于两种场景:

  • 传递指针数组:指针数组名本身就是二级指针(如char *str_arr[]等价于char **str_arr)。

  • 传递动态二维数组:通过malloc动态分配的二维数组(如int **arr),其数组名也是二级指针。

  • 下面通过两个示例讲解二级指针传参的用法。

    示例1 二级指针传递指针数组

    之前的指针数组排序中,bubble_sort_str_ptr(char *str_arr[], int len)的参数char *str_arr[]等价于char **str_arr(二级指针)。这里显式用二级指针参数重写,更直观展示二级指针传参逻辑。

    #include <stdio.h>
    #include <string.h>

    // 显式用二级指针参数:pp 指向指针数组的指针(即二级指针)
    void bubble_sort_2ptr(char **pp, int len) {
    int i, j;
    char *temp;
    int swapped;

    for (i = 0; i < len – 1; i++) {
    swapped = 0;
    for (j = 0; j < len – i – 1; j++) {
    if (strcmp(pp[j], pp[j + 1]) > 0) { // 比较字符串
    temp = pp[j]; // 交换指针(通过二级指针访问元素)
    pp[j] = pp[j + 1];
    pp[j + 1] = temp;
    swapped = 1;
    }
    }
    if (!swapped) break;
    }
    }

    int main() {
    char *fruits[] = {"banana", "apple", "cherry", "date"};
    int len = sizeof(fruits) / sizeof(fruits[0]);

    // fruits 是指针数组名,退化为二级指针 char **,直接传递给函数
    bubble_sort_2ptr(fruits, len);

    printf("排序后(二级指针传参):");
    for (int i = 0; i < len; i++) {
    printf("%s ", fruits[i]);
    }
    printf("\\n");
    return 0;
    }

    核心逻辑:二级指针pp指向指针数组的首元素(即第一个字符串的地址),通过pp[j]访问第j个字符串的指针,交换时直接操作指针值。

    示例2 二级指针传递动态二维数组(动态分配内存)

    动态二维数组通过malloc分配:先分配行指针数组(int **arr),再为每行分配列空间。此时arr是二级指针,可直接传递给排序函数。

    #include <stdio.h>
    #include <stdlib.h>

    // 冒泡排序动态二维数组(整体排序,视为一维数组)
    // 参数:pp 动态二维数组首地址(二级指针),rows 行数,cols 列数
    void bubble_sort_dynamic_2d(int **pp, int rows, int cols) {
    int total = rows * cols;
    int i, j, temp;
    int swapped;

    for (i = 0; i < total – 1; i++) {
    swapped = 0;
    for (j = 0; j < total – i – 1; j++) {
    // 计算行列坐标(动态数组同样连续存储)
    int row1 = j / cols, col1 = j % cols;
    int row2 = (j + 1) / cols, col2 = (j + 1) % cols;

    if (pp[row1][col1] > pp[row2][col2]) {
    temp = pp[row1][col1];
    pp[row1][col1] = pp[row2][col2];
    pp[row2][col2] = temp;
    swapped = 1;
    }
    }
    if (!swapped) break;
    }
    }

    // 打印动态二维数组
    void print_dynamic_2d(int **pp, int rows, int cols) {
    int i, j;
    for (i = 0; i < rows; i++) {
    for (j = 0; j < cols; j++) {
    printf("%d ", pp[i][j]);
    }
    printf("\\n");
    }
    }

    int main() {
    int rows = 3, cols = 4;
    int **matrix = (int **)malloc(rows * sizeof(int *)); // 分配行指针数组
    for (int i = 0; i < rows; i++) {
    matrix[i] = (int *)malloc(cols * sizeof(int)); // 为每行分配列空间
    }

    // 初始化动态数组
    int init_data[3][4] = {{9, 5, 7, 3}, {2, 8, 1, 6}, {4, 0, 10, 12}};
    for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
    matrix[i][j] = init_data[i][j];
    }
    }

    printf("动态数组排序前:\\n");
    print_dynamic_2d(matrix, rows, cols);

    bubble_sort_dynamic_2d(matrix, rows, cols); // 传递二级指针

    printf("动态数组排序后(整体升序):\\n");
    print_dynamic_2d(matrix, rows, cols);

    // 释放内存(避免泄漏)
    for (int i = 0; i < rows; i++) free(matrix[i]);
    free(matrix);
    return 0;
    }

    核心逻辑:动态二维数组的二级指针pp指向行指针数组,通过pp[i][j]访问元素,排序时视为一维数组处理(利用内存连续性)。

    六、总结

    数组类型

    传递方式

    本质(退化后)

    排序核心思路

    典型场景

    一维数组

    int arr[]或 int *arr

    一级指针

    相邻元素比较交换

    普通数值数组排序

    二维数组(静态)

    int arr[][N]或 int (*arr)[N]

    数组指针(行指针)

    视为一维数组整体排序

    固定列数的矩阵排序

    指针数组

    char *arr[]或 char **arr

    二级指针

    交换指针(高效)或交换内容

    字符串数组按字典序排序

    动态二维数组

    int **arr

    二级指针

    视为一维数组整体排序

    运行时动态创建的多维数组排序

    二级指针传参的关键:明确其指向“指针数组”或“动态二维数组的行指针数组”,通过解引用(pp[j]或pp[i][j])访问元素,排序逻辑与普通数组一致,仅传递方式不同。掌握二级指针传参,能灵活处理更复杂的数组场景(如动态内存、多级指针数据结构)。

    赞(0)
    未经允许不得转载:171主机测评 » 冒泡排序与数组传递全解析 一维二维指针数组及二级指针应用指南
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址