c++:模板的应用

发布于:2025-08-01 ⋅ 阅读:(15) ⋅ 点赞:(0)

请使用函数模板,写一个能够针对所有数据类型的数据的快速排序函数,并多写几个数组做测试

#include <iostream>
#include <string>
#include <cstring>

// 交换两个元素的值 - 通用模板
template <typename T>
void swap(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

// 分区操作 - 通用模板
template <typename T>
int partition(T arr[], int low, int high) {
    T pivot = arr[high];  // 选择最右边的元素作为基准
    int i = low - 1;      // 小于基准的元素的索引
    
    for (int j = low; j <= high - 1; j++) {
        // 如果当前元素小于或等于基准
        if (arr[j] <= pivot) {
            i++;  // 增加小于基准区域的索引
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i + 1], arr[high]);
    return i + 1;
}

// 快速排序函数模板 - 通用版本
template <typename T>
void quickSort(T arr[], int low, int high) {
    if (low < high) {
        // pi是分区索引,arr[pi]现在在正确的位置
        int pi = partition(arr, low, high);
        
        // 分别对基准元素左右两边的子数组进行排序
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

// 为C风格字符串提供全特化的分区函数
template <>
int partition<char*>(char* arr[], int low, int high) {
    char* pivot = arr[high];  // 选择最右边的元素作为基准
    int i = low - 1;          // 小于基准的元素的索引
    
    for (int j = low; j <= high - 1; j++) {
        // 使用strcmp比较C风格字符串
        if (std::strcmp(arr[j], pivot) <= 0) {
            i++;  // 增加小于基准区域的索引
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i + 1], arr[high]);
    return i + 1;
}

// 为C风格字符串提供全特化的快速排序函数
template <>
void quickSort<char*>(char* arr[], int low, int high) {
    if (low < high) {
        // 使用特化的partition函数
        int pi = partition(arr, low, high);
        
        // 递归排序子数组
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

// 打印数组元素 - 通用模板
template <typename T>
void printArray(T arr[], int size) {
    for (int i = 0; i < size; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
}

// 为C风格字符串数组提供特化的打印函数
template <>
void printArray<char*>(char* arr[], int size) {
    for (int i = 0; i < size; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
}

int main() {
    // 测试整数数组 (使用通用模板)
    int intArr[] = {10, 7, 8, 9, 1, 5};
    int n = sizeof(intArr) / sizeof(intArr[0]);
    std::cout << "整数数组排序前: ";
    printArray(intArr, n);
    quickSort(intArr, 0, n - 1);
    std::cout << "整数数组排序后: ";
    printArray(intArr, n);
    std::cout << std::endl;
    
    // 测试浮点数数组 (使用通用模板)
    double doubleArr[] = {3.14, 1.59, 2.65, 0.12, 5.75};
    int m = sizeof(doubleArr) / sizeof(doubleArr[0]);
    std::cout << "浮点数数组排序前: ";
    printArray(doubleArr, m);
    quickSort(doubleArr, 0, m - 1);
    std::cout << "浮点数数组排序后: ";
    printArray(doubleArr, m);
    std::cout << std::endl;
    
    // 测试字符数组 (使用通用模板)
    char charArr[] = {'d', 'a', 'c', 'b', 'f', 'e'};
    int p = sizeof(charArr) / sizeof(charArr[0]);
    std::cout << "字符数组排序前: ";
    printArray(charArr, p);
    quickSort(charArr, 0, p - 1);
    std::cout << "字符数组排序后: ";
    printArray(charArr, p);
    std::cout << std::endl;
    
    // 测试std::string数组 (使用通用模板)
    std::string strArr[] = {"banana", "apple", "orange", "grape", "cherry"};
    int q = sizeof(strArr) / sizeof(strArr[0]);
    std::cout << "std::string数组排序前: ";
    printArray(strArr, q);
    quickSort(strArr, 0, q - 1);
    std::cout << "std::string数组排序后: ";
    printArray(strArr, q);
    std::cout << std::endl;
    
    // 测试C风格字符串数组 (使用全特化版本)
    char* cstrArr[] = {"banana", "apple", "orange", "grape", "cherry"};
    int r = sizeof(cstrArr) / sizeof(cstrArr[0]);
    std::cout << "C风格字符串数组排序前: ";
    printArray(cstrArr, r);
    quickSort(cstrArr, 0, r - 1);  // 调用特化版本
    std::cout << "C风格字符串数组排序后: ";
    printArray(cstrArr, r);
    
    return 0;
}

请使用函数模板,写一个能够针对所有数据类型的数据的快速排序,展示快排过程,并多写几个数组做测试

#include <iostream>
#include <string>
#include <cstring>
#include <iomanip>

// 全局变量,用于记录递归深度和步骤
int stepCount = 0;
int recursionDepth = 0;

// 打印数组元素 - 通用模板
template <typename T>
void printArray(T arr[], int size, int low = -1, int high = -1, int pivot = -1) {
    std::cout << "  ";
    for (int i = 0; i < size; i++) {
        // 标记当前处理范围和基准元素
        if (i == pivot) {
            std::cout << "[" << arr[i] << "] ";
        } else if (low != -1 && high != -1 && i >= low && i <= high) {
            std::cout << "<" << arr[i] << "> ";
        } else {
            std::cout << " " << arr[i] << "  ";
        }
    }
    std::cout << std::endl;
}

// 为const char*字符串数组提供特化的打印函数
template <>
void printArray<const char*>(const char* arr[], int size, int low, int high, int pivot) {
    std::cout << "  ";
    for (int i = 0; i < size; i++) {
        // 标记当前处理范围和基准元素
        if (i == pivot) {
            std::cout << "[" << arr[i] << "] ";
        } else if (low != -1 && high != -1 && i >= low && i <= high) {
            std::cout << "<" << arr[i] << "> ";
        } else {
            std::cout << " " << arr[i] << "  ";
        }
    }
    std::cout << std::endl;
}

// 交换两个元素的值 - 通用模板
template <typename T>
void swap(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

// 分区操作并展示过程 - 通用模板
template <typename T>
int partition(T arr[], int low, int high, int size) {
    T pivot = arr[high];  // 选择最右边的元素作为基准
    int i = low - 1;      // 小于基准的元素的索引
    
    std::cout << std::setw(2) << stepCount++ << ". 分区: 基准元素 = " << pivot 
              << ", 范围: [" << low << "," << high << "]" << std::endl;
    std::cout << "   初始状态: ";
    printArray(arr, size, low, high, high);
    
    for (int j = low; j <= high - 1; j++) {
        // 如果当前元素小于或等于基准
        if (arr[j] <= pivot) {
            i++;  // 增加小于基准区域的索引
            if (i != j) {
                swap(arr[i], arr[j]);
                std::cout << "   交换后:   ";
                printArray(arr, size, low, high, high);
            }
        }
    }
    
    // 将基准元素放到正确的位置
    swap(arr[i + 1], arr[high]);
    std::cout << "   分区完成: ";
    printArray(arr, size, low, high, i + 1);
    std::cout << "   基准位置: " << i + 1 << std::endl << std::endl;
    
    return i + 1;
}

// 为const char*提供全特化的分区函数
template <>
int partition<const char*>(const char* arr[], int low, int high, int size) {
    const char* pivot = arr[high];  // 选择最右边的元素作为基准
    int i = low - 1;                // 小于基准的元素的索引
    
    std::cout << std::setw(2) << stepCount++ << ". 分区: 基准元素 = " << pivot 
              << ", 范围: [" << low << "," << high << "]" << std::endl;
    std::cout << "   初始状态: ";
    printArray(arr, size, low, high, high);
    
    for (int j = low; j <= high - 1; j++) {
        // 使用strcmp比较C风格字符串
        if (std::strcmp(arr[j], pivot) <= 0) {
            i++;  // 增加小于基准区域的索引
            if (i != j) {
                swap(const_cast<const char*&>(arr[i]), const_cast<const char*&>(arr[j]));
                std::cout << "   交换后:   ";
                printArray(arr, size, low, high, high);
            }
        }
    }
    
    // 将基准元素放到正确的位置
    swap(const_cast<const char*&>(arr[i + 1]), const_cast<const char*&>(arr[high]));
    std::cout << "   分区完成: ";
    printArray(arr, size, low, high, i + 1);
    std::cout << "   基准位置: " << i + 1 << std::endl << std::endl;
    
    return i + 1;
}

// 快速排序函数模板并展示过程 - 通用版本
template <typename T>
void quickSort(T arr[], int low, int high, int size) {
    recursionDepth++;
    if (low < high) {
        // 打印递归深度信息
        std::cout << "递归深度 " << recursionDepth << ": 处理子数组 [" << low << "," << high << "]" << std::endl;
        
        // pi是分区索引,arr[pi]现在在正确的位置
        int pi = partition(arr, low, high, size);
        
        // 分别对基准元素左右两边的子数组进行排序
        quickSort(arr, low, pi - 1, size);
        quickSort(arr, pi + 1, high, size);
    }
    recursionDepth--;
}

// 测试函数
template <typename T>
void testQuickSort(T arr[], int size, const std::string& typeName) {
    std::cout << "================================================" << std::endl;
    std::cout << typeName << "数组快速排序过程展示:" << std::endl;
    std::cout << "初始数组: ";
    printArray(arr, size);
    std::cout << std::endl;
    
    // 重置步骤计数器
    stepCount = 0;
    recursionDepth = 0;
    
    // 执行快速排序
    quickSort(arr, 0, size - 1, size);
    
    std::cout << "排序完成数组: ";
    printArray(arr, size);
    std::cout << "================================================" << std::endl << std::endl;
}

int main() {
    // 测试整数数组
    int intArr[] = {10, 7, 8, 9, 1, 5};
    int n = sizeof(intArr) / sizeof(intArr[0]);
    testQuickSort(intArr, n, "整数");
    
    // 测试浮点数数组
    double doubleArr[] = {3.14, 1.59, 2.65, 0.12};
    int m = sizeof(doubleArr) / sizeof(doubleArr[0]);
    testQuickSort(doubleArr, m, "浮点数");
    
    // 测试字符数组
    char charArr[] = {'d', 'a', 'c', 'b', 'f'};
    int p = sizeof(charArr) / sizeof(charArr[0]);
    testQuickSort(charArr, p, "字符");
    
    // 测试std::string数组
    std::string strArr[] = {"banana", "apple", "orange", "grape"};
    int q = sizeof(strArr) / sizeof(strArr[0]);
    testQuickSort(strArr, q, "std::string");
    
    // 测试C风格字符串数组(使用const char*避免警告)
    const char* cstrArr[] = {"dog", "cat", "elephant", "ant"};
    int r = sizeof(cstrArr) / sizeof(cstrArr[0]);
    testQuickSort(cstrArr, r, "C风格字符串");
    
    return 0;
}
    


网站公告

今日签到

点亮在社区的每一天
去签到