You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现支持int、float、C字符串的C语言通用冒泡排序?

修复通用冒泡排序实现的问题

原代码中的核心问题

  • 参数类型错误: bubbleSort 的第一个参数是 void* arr[](void指针数组),但通用排序应该接收单个 void* 指向数组起始地址,这样才能处理任意类型的连续数组。
  • 比较逻辑错误: 直接比较元素地址 &arr[j] > &arr[j+1] 毫无意义,我们需要根据元素类型的值进行比较,因此必须传入一个自定义比较函数。
  • 元素访问错误: 对于 void* 类型的数组,不能直接用下标访问,需要通过 char* 转换后按元素大小计算偏移量来获取元素地址。
  • 打印方式错误: printf(&arr[i]) 不符合 printf 的调用规范,且无法通用打印不同类型的元素,应该在排序完成后根据类型单独处理打印。
  • 主函数数组声明错误: int* arr[] = {0,1,...} 是指针数组,这里的整数值会被当作指针地址(比如0是NULL指针),应该声明为普通的 int 数组。

修复后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>

void swapG(void* a, void* b, int elemSize)
{
    void* temp = malloc(elemSize);
    assert(temp != NULL);
    memcpy(temp, a, elemSize);
    memcpy(a, b, elemSize);
    memcpy(b, temp, elemSize);
    free(temp);
}

// 比较函数指针类型:返回值 <0 表示a<b,=0表示相等,>0表示a>b
typedef int (*CompareFunc)(const void* a, const void* b);

void bubbleSort(void* arr, int n, int elemSize, CompareFunc compare)
{
    int i, j;
    bool swapped;
    // 将void*转换为char*以便按字节计算偏移
    char* arrBytes = (char*)arr;
    
    for (i = 0; i < n - 1; i++) {
        swapped = false;
        for (j = 0; j < n - i - 1; j++) {
            // 获取第j个和j+1个元素的地址
            void* elemJ = arrBytes + j * elemSize;
            void* elemJ1 = arrBytes + (j+1)*elemSize;
            
            if (compare(elemJ, elemJ1) > 0) {
                swapG(elemJ, elemJ1, elemSize);
                swapped = true;
            }
        }
        if (!swapped) break;
    }
}

// 针对不同类型的比较函数
int compareInt(const void* a, const void* b)
{
    return *(const int*)a - *(const int*)b;
}

int compareFloat(const void* a, const void* b)
{
    float diff = *(const float*)a - *(const float*)b;
    return diff > 0 ? 1 : (diff < 0 ? -1 : 0);
}

int compareString(const void* a, const void* b)
{
    return strcmp(*(const char**)a, *(const char**)b);
}

// 打印函数示例
void printIntArray(const int* arr, int n)
{
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

void printFloatArray(const float* arr, int n)
{
    for (int i = 0; i < n; i++) {
        printf("%.2f ", arr[i]);
    }
    printf("\n");
}

void printStringArray(const char** arr, int n)
{
    for (int i = 0; i < n; i++) {
        printf("%s ", arr[i]);
    }
    printf("\n");
}

int main()
{
    // 测试int数组
    int intArr[] = {0,1,4,6,9,10,13,7};
    int nInt = sizeof(intArr)/sizeof(intArr[0]);
    bubbleSort(intArr, nInt, sizeof(int), compareInt);
    printf("排序后的int数组:");
    printIntArray(intArr, nInt);
    
    // 测试float数组
    float floatArr[] = {3.14, 1.59, 2.65, 0.78, 4.20};
    int nFloat = sizeof(floatArr)/sizeof(floatArr[0]);
    bubbleSort(floatArr, nFloat, sizeof(float), compareFloat);
    printf("排序后的float数组:");
    printFloatArray(floatArr, nFloat);
    
    // 测试字符串数组
    const char* strArr[] = {"banana", "apple", "cherry", "date", "elderberry"};
    int nStr = sizeof(strArr)/sizeof(strArr[0]);
    bubbleSort(strArr, nStr, sizeof(char*), compareString);
    printf("排序后的字符串数组:");
    printStringArray(strArr, nStr);
    
    return 0;
}

关键修复说明

  1. 引入比较函数: 通过 CompareFunc 类型定义,让 bubbleSort 接收一个自定义比较函数,这样可以处理int、float、字符串等不同类型的比较逻辑。
  2. 正确的元素地址计算: 将 void* arr 转换为 char*,然后通过 j * elemSize 计算每个元素的偏移地址,确保能正确访问任意类型的数组元素。
  3. 修正数组传递: 在main中使用普通数组(而非指针数组),并将数组名直接传递给 bubbleSort(数组名会自动 decay 为指向首元素的指针)。
  4. 单独处理打印: 针对不同类型编写专用的打印函数,避免通用函数的复杂性,同时保证打印正确。
  5. 简化swapG: 去掉了不必要的 (char*) 强制转换,malloc(elemSize) 已经足够。

内容的提问来源于stack exchange,提问作者thedrooster

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 07:25:03