CCF GESP C++ G5核心算法模板代码集

CCF GESP C++ G5核心算法模板代码集

一、初等数论相关

1. 辗转相除法(欧几里得算法)- 求最大公约数

#include <algorithm>
using namespace std;

// 迭代版(效率更高,避免栈溢出)
int gcd(int a, int b) {
    a = abs(a); // 处理负数情况
    b = abs(b);
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

// 递归版(代码简洁,逻辑直观)
int gcd_recursive(int a, int b) {
    a = abs(a);
    b = abs(b);
    return b == 0 ? a : gcd_recursive(b, a % b);
}

// 扩展:求最小公倍数(基于最大公约数)
int lcm(int a, int b) {
    if (a == 0 || b == 0) return 0; // 避免除以零
    return a / gcd(a, b) * b; // 先除后乘,避免溢出
}

2. 素数判断(高效版)

#include <cmath>
using namespace std;

bool is_prime(int num) {
    if (num < 2) return false; // 小于2的数不是素数
    if (num == 2 || num == 3) return true; // 2和3是素数
    if (num % 2 == 0 || num % 3 == 0) return false; // 排除偶数和3的倍数
    int end = sqrt(num) + 1;
    // 仅遍历6k±1形式的数,优化效率
    for (int i = 5; i <= end; i += 6) {
        if (num % i == 0 || num % (i + 2) == 0) {
            return false;
        }
    }
    return true;
}

3. 质因数分解(唯一分解定理应用)

#include <vector>
#include <cmath>
using namespace std;

// 返回质因数及其指数对(如12返回[(2,2), (3,1)])
vector<pair<int, int>> prime_factorization(int n) {
    vector<pair<int, int>> factors;
    if (n <= 1) return factors;
    
    // 处理2的因子
    int cnt = 0;
    while (n % 2 == 0) {
        cnt++;
        n /= 2;
    }
    if (cnt > 0) {
        factors.emplace_back(2, cnt);
    }
    
    // 处理奇数因子
    for (int i = 3; i <= sqrt(n); i += 2) {
        cnt = 0;
        while (n % i == 0) {
            cnt++;
            n /= i;
        }
        if (cnt > 0) {
            factors.emplace_back(i, cnt);
        }
    }
    
    // 剩余的n为素数
    if (n > 2) {
        factors.emplace_back(n, 1);
    }
    return factors;
}

4. 埃拉托斯特尼筛法(生成素数表)

#include <vector>
using namespace std;

// 生成[2, n]范围内的素数表
vector<bool> sieve_Eratosthenes(int n) {
    vector<bool> is_prime(n + 1, true);
    if (n >= 0) is_prime[0] = false;
    if (n >= 1) is_prime[1] = false;
    for (int i = 2; i * i <= n; ++i) {
        if (is_prime[i]) {
            // 从i*i开始标记,优化效率(小于i*i的倍数已被标记)
            for (int j = i * i; j <= n; j += i) {
                is_prime[j] = false;
            }
        }
    }
    return is_prime;
}

5. 线性筛法(欧拉筛)- 高效生成素数表

#include <vector>
using namespace std;

// 生成[2, n]范围内的素数表,每个合数仅被最小质因子标记
vector<int> sieve_linear(int n) {
    vector<bool> is_prime(n + 1, true);
    vector<int> primes;
    if (n >= 0) is_prime[0] = false;
    if (n >= 1) is_prime[1] = false;
    for (int i = 2; i <= n; ++i) {
        if (is_prime[i]) {
            primes.push_back(i);
        }
        // 遍历已找到的素数,标记i*primes[j]为合数
        for (int j = 0; j < primes.size() && 1LL * i * primes[j] <= n; ++j) {
            is_prime[i * primes[j]] = false;
            if (i % primes[j] == 0) {
                break; // 保证每个合数仅被最小质因子标记
            }
        }
    }
    return primes;
}

二、高精度运算(数组模拟)

1. 高精度加法(支持大整数相加)

#include <vector>
#include <algorithm>
using namespace std;

// a和b为逆序存储的大整数(如123存储为[3,2,1])
vector<int> high_precision_add(vector<int> a, vector<int> b) {
    vector<int> res;
    int carry = 0;
    int i = 0;
    // 逐位相加,处理进位
    while (i < a.size() || i < b.size() || carry > 0) {
        int sum = carry;
        if (i < a.size()) sum += a[i];
        if (i < b.size()) sum += b[i];
        res.push_back(sum % 10); // 存储当前位
        carry = sum / 10; // 更新进位
        i++;
    }
    return res;
}

// 辅助函数:将字符串转换为逆序数组
vector<int> str_to_rev_arr(string s) {
    vector<int> res;
    for (int i = s.size() - 1; i >= 0; --i) {
        res.push_back(s[i] - '0');
    }
    return res;
}

// 辅助函数:将逆序数组转换为字符串
string rev_arr_to_str(vector<int> arr) {
    string res;
    // 去除前导零(逆序存储的末尾零)
    while (arr.size() > 1 && arr.back() == 0) {
        arr.pop_back();
    }
    for (int i = arr.size() - 1; i >= 0; --i) {
        res.push_back(arr[i] + '0');
    }
    return res;
}

2. 高精度减法(支持大整数相减,a >= b)

#include <vector>
#include <algorithm>
using namespace std;

// a和b为逆序存储,且a表示的数 >= b表示的数
vector<int> high_precision_sub(vector<int> a, vector<int> b) {
    vector<int> res;
    int borrow = 0;
    int i = 0;
    while (i < a.size() || i < b.size()) {
        int sub = a[i] - borrow;
        if (i < b.size()) sub -= b[i];
        if (sub < 0) {
            sub += 10;
            borrow = 1;
        } else {
            borrow = 0;
        }
        res.push_back(sub);
        i++;
    }
    // 去除前导零
    while (res.size() > 1 && res.back() == 0) {
        res.pop_back();
    }
    return res;
}

3. 高精度乘法(大整数 × 小整数)

#include <vector>
using namespace std;

// a为逆序存储的大整数,b为小整数(int范围)
vector<int> high_precision_mul_small(vector<int> a, int b) {
    vector<int> res;
    int carry = 0;
    for (int i = 0; i < a.size() || carry > 0; ++i) {
        long long product = carry;
        if (i < a.size()) product += 1LL * a[i] * b; // 避免溢出
        res.push_back(product % 10);
        carry = product / 10;
    }
    // 去除前导零
    while (res.size() > 1 && res.back() == 0) {
        res.pop_back();
    }
    return res;
}

4. 高精度除法(大整数 ÷ 小整数)

#include <vector>
#include <algorithm>
using namespace std;

// a为逆序存储的大整数,b为小整数(int范围),返回(商, 余数)
pair<vector<int>, int> high_precision_div_small(vector<int> a, int b) {
    vector<int> quotient;
    int remainder = 0;
    // 正序遍历(从高位到低位)
    for (int i = a.size() - 1; i >= 0; --i) {
        long long dividend = 1LL * remainder * 10 + a[i];
        quotient.push_back(dividend / b);
        remainder = dividend % b;
    }
    // 逆序得到正确的商(因为quotient当前是正序存储)
    reverse(quotient.begin(), quotient.end());
    // 去除前导零
    while (quotient.size() > 1 && quotient.back() == 0) {
        quotient.pop_back();
    }
    return {quotient, remainder};
}

三、链表操作

1. 单链表结构体定义与基本操作

#include <iostream>
#include <string>
using namespace std;

// 单链表节点结构体
struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
    ListNode(int x, ListNode* nxt) : val(x), next(nxt) {}
};

// 插入节点到链表头部
ListNode* insert_head(ListNode* head, int val) {
    ListNode* new_node = new ListNode(val);
    new_node->next = head;
    return new_node;
}

// 插入节点到链表尾部
ListNode* insert_tail(ListNode* head, int val) {
    ListNode* new_node = new ListNode(val);
    if (head == nullptr) {
        return new_node;
    }
    ListNode* curr = head;
    while (curr->next != nullptr) {
        curr = curr->next;
    }
    curr->next = new_node;
    return head;
}

// 删除链表中所有值为val的节点(含虚拟头节点优化)
ListNode* remove_elements(ListNode* head, int val) {
    ListNode* dummy = new ListNode(0); // 虚拟头节点,统一处理头节点
    dummy->next = head;
    ListNode* curr = dummy;
    while (curr->next != nullptr) {
        if (curr->next->val == val) {
            ListNode* temp = curr->next;
            curr->next = curr->next->next;
            delete temp; // 释放内存
        } else {
            curr = curr->next;
        }
    }
    ListNode* new_head = dummy->next;
    delete dummy; // 释放虚拟头节点
    return new_head;
}

// 遍历链表并打印
void traverse_list(ListNode* head) {
    ListNode* curr = head;
    while (curr != nullptr) {
        cout << curr->val << " ";
        curr = curr->next;
    }
    cout << endl;
}

// 释放链表内存
void free_list(ListNode* head) {
    ListNode* curr = head;
    while (curr != nullptr) {
        ListNode* temp = curr;
        curr = curr->next;
        delete temp;
    }
}

2. 双链表结构体定义与基本操作

#include <iostream>
using namespace std;

// 双链表节点结构体
struct DoublyListNode {
    int val;
    DoublyListNode* prev;
    DoublyListNode* next;
    DoublyListNode(int x) : val(x), prev(nullptr), next(nullptr) {}
};

// 在节点p之后插入节点s
void insert_after(DoublyListNode* p, int val) {
    if (p == nullptr) return;
    DoublyListNode* s = new DoublyListNode(val);
    s->next = p->next;
    s->prev = p;
    if (p->next != nullptr) {
        p->next->prev = s;
    }
    p->next = s;
}

// 删除节点p(p非空)
void delete_node(DoublyListNode*& head, DoublyListNode* p) {
    if (p == nullptr) return;
    if (p->prev != nullptr) {
        p->prev->next = p->next;
    } else {
        head = p->next; // p是头节点
    }
    if (p->next != nullptr) {
        p->next->prev = p->prev;
    }
    delete p;
}

// 遍历双链表(正序)
void traverse_doubly_list(DoublyListNode* head) {
    DoublyListNode* curr = head;
    while (curr != nullptr) {
        cout << curr->val << " ";
        curr = curr->next;
    }
    cout << endl;
}

3. 循环链表判断(Floyd快慢指针法)

#include <iostream>
using namespace std;

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};

// 判断单链表是否有环
bool has_cycle(ListNode* head) {
    if (head == nullptr || head->next == nullptr) {
        return false;
    }
    ListNode* slow = head;
    ListNode* fast = head->next;
    while (fast != nullptr && fast->next != nullptr) {
        if (slow == fast) {
            return true; // 快慢指针相遇,存在环
        }
        slow = slow->next;      // 慢指针走1步
        fast = fast->next->next;// 快指针走2步
    }
    return false; // 快指针到达终点,无环
}

四、查找算法

1. 二分查找(有序数组查找目标值)

#include <vector>
using namespace std;

// 迭代版:在有序数组nums中查找target,返回索引(-1表示未找到)
int binary_search(vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size() - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2; // 避免溢出
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;
}

// 递归版:在[left, right]区间查找
int binary_search_recursive(vector<int>& nums, int target, int left, int right) {
    if (left > right) return -1;
    int mid = left + (right - left) / 2;
    if (nums[mid] == target) {
        return mid;
    } else if (nums[mid] < target) {
        return binary_search_recursive(nums, target, mid + 1, right);
    } else {
        return binary_search_recursive(nums, target, left, mid - 1);
    }
}

// 扩展:查找目标值的左边界(存在重复元素)
int find_left_bound(vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size() - 1;
    int res = -1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            res = mid;
            right = mid - 1; // 继续向左查找左边界
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return res;
}

2. 二分答案(查找满足条件的最值)

#include <vector>
using namespace std;

// 示例:在有序数组中查找大于等于target的最小元素
int binary_answer(vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size(); // 右边界为n,处理所有元素都小于target的情况
    while (left < right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] >= target) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }
    return left < nums.size() ? nums[left] : -1; // 不存在返回-1
}

五、排序算法

1. 归并排序(稳定排序,O(n log n))

#include <vector>
using namespace std;

// 合并两个有序子数组[left, mid]和[mid+1, right]
void merge(vector<int>& arr, int left, int mid, int right) {
    int n1 = mid - left + 1;
    int n2 = right - mid;
    vector<int> L(n1), R(n2);
    // 复制数据到临时数组
    for (int i = 0; i < n1; ++i) L[i] = arr[left + i];
    for (int j = 0; j < n2; ++j) R[j] = arr[mid + 1 + j];
    
    // 合并临时数组到原数组
    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            arr[k++] = L[i++];
        } else {
            arr[k++] = R[j++];
        }
    }
    // 复制剩余元素
    while (i < n1) arr[k++] = L[i++];
    while (j < n2) arr[k++] = R[j++];
}

// 归并排序主函数
void merge_sort(vector<int>& arr, int left, int right) {
    if (left < right) {
        int mid = left + (right - left) / 2; // 避免溢出
        merge_sort(arr, left, mid);       // 左子数组排序
        merge_sort(arr, mid + 1, right);  // 右子数组排序
        merge(arr, left, mid, right);     // 合并两个有序子数组
    }
}

2. 快速排序(不稳定排序,平均O(n log n))

#include <vector>
#include <algorithm>
using namespace std;

// 分区函数:返回基准元素的最终位置
int partition(vector<int>& arr, int low, int high) {
    int pivot = arr[high]; // 选择最右侧元素作为基准
    int i = low - 1;       // i指向小于基准区域的末尾
    for (int j = low; j < high; ++j) {
        if (arr[j] <= pivot) {
            i++;
            swap(arr[i], arr[j]); // 将小于等于基准的元素移入左侧区域
        }
    }
    swap(arr[i + 1], arr[high]); // 基准元素放到最终位置
    return i + 1;
}

// 快速排序主函数
void quick_sort(vector<int>& arr, int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high); // 分区
        quick_sort(arr, low, pi - 1);      // 左子数组排序
        quick_sort(arr, pi + 1, high);     // 右子数组排序
    }
}

// 扩展:随机选择基准,优化有序数组的情况
int random_partition(vector<int>& arr, int low, int high) {
    int rand_idx = low + rand() % (high - low + 1); // 随机选择基准索引
    swap(arr[rand_idx], arr[high]);                // 基准移到末尾
    return partition(arr, low, high);
}

void quick_sort_optimized(vector<int>& arr, int low, int high) {
    if (low < high) {
        int pi = random_partition(arr, low, high);
        quick_sort_optimized(arr, low, pi - 1);
        quick_sort_optimized(arr, pi + 1, high);
    }
}

六、贪心算法

1. 活动安排问题(最多不重叠活动)

#include <vector>
#include <algorithm>
using namespace std;

// 活动结构体:start为开始时间,end为结束时间
struct Activity {
    int start;
    int end;
};

// 按结束时间升序排序(贪心选择核心)
bool cmp(Activity a, Activity b) {
    return a.end < b.end;
}

// 选择最多不重叠的活动,返回最大活动数
int max_activities(vector<Activity>& activities) {
    if (activities.empty()) return 0;
    sort(activities.begin(), activities.end(), cmp);
    
    int count = 1;
    int last_end = activities[0].end;
    for (int i = 1; i < activities.size(); ++i) {
        // 下一个活动的开始时间 >= 上一个活动的结束时间,选择该活动
        if (activities[i].start >= last_end) {
            count++;
            last_end = activities[i].end;
        }
    }
    return count;
}

2. 硬币找零问题(最少硬币数)

#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

const int MAX_COINS = 10;
int result[MAX_COINS] = {0}; // 存储每种硬币的使用数量

// 贪心策略:优先使用大面值硬币
int find_min_coins(vector<int>& coins, int amount) {
    sort(coins.begin(), coins.end(), greater<int>()); // 硬币面值从大到小排序
    int n = coins.size();
    int total = 0; // 总硬币数
    for (int i = 0; i < n; ++i) {
        if (amount <= 0) break;
        int num = amount / coins[i]; // 当前面值最多使用的数量
        result[i] = num;
        total += num;
        amount -= num * coins[i]; // 剩余金额
    }
    return amount == 0 ? total : -1; // 无法找零返回-1
}

// 输出找零方案
void print_coins(vector<int>& coins) {
    cout << "找零方案:" << endl;
    for (int i = 0; i < coins.size(); ++i) {
        if (result[i] > 0) {
            cout << coins[i] << "元:" << result[i] << "枚" << endl;
        }
    }
}

3. 巧夺大奖(最大化游戏奖励)

#include <vector>
#include <algorithm>
using namespace std;

struct Game {
    int deadline; // 完成期限
    int reward;   // 奖励
};

// 按奖励从大到小排序(优先选择高奖励游戏)
bool game_cmp(Game a, Game b) {
    return a.reward > b.reward;
}

// 最大化获得的奖励,n为游戏数量(同时也是时间段数量)
int max_game_reward(vector<Game>& games, int n) {
    sort(games.begin(), games.end(), game_cmp);
    vector<bool> used(n, false); // 标记时间段是否被使用
    int total = 0;
    
    for (auto& game : games) {
        // 从最后期限往前找可用时间段
        for (int t = min(game.deadline - 1, n - 1); t >= 0; --t) {
            if (!used[t]) {
                used[t] = true;
                total += game.reward;
                break;
            }
        }
    }
    return total;
}

4. 分糖果问题(每个孩子至少1颗,评分高的孩子分更多)

#include <vector>
#include <algorithm>
using namespace std;

// 贪心策略:左右两次遍历,保证相邻评分高的孩子糖果更多
int candy(vector<int>& ratings) {
    int n = ratings.size();
    vector<int> candies(n, 1); // 每个孩子至少1颗
    
    // 从左到右:右边评分高的比左边多1颗
    for (int i = 1; i < n; ++i) {
        if (ratings[i] > ratings[i-1]) {
            candies[i] = candies[i-1] + 1;
        }
    }
    
    // 从右到左:左边评分高的比右边多1颗(取最大值保证两边都满足)
    for (int i = n-2; i >= 0; --i) {
        if (ratings[i] > ratings[i+1]) {
            candies[i] = max(candies[i], candies[i+1] + 1);
        }
    }
    
    // 计算总糖果数
    int total = 0;
    for (int c : candies) total += c;
    return total;
}

七、分治算法(归并排序和快速排序)

1. 归并排序(稳定排序,O(n log n))

#include <vector>
using namespace std;

// 合并两个有序子数组[left, mid]和[mid+1, right]
void merge(vector<int>& arr, int left, int mid, int right) {
    int n1 = mid - left + 1;
    int n2 = right - mid;
    vector<int> L(n1), R(n2);
    
    // 复制数据到临时数组
    for (int i = 0; i < n1; ++i) L[i] = arr[left + i];
    for (int j = 0; j < n2; ++j) R[j] = arr[mid + 1 + j];
    
    // 合并临时数组到原数组
    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            arr[k++] = L[i++];
        } else {
            arr[k++] = R[j++];
        }
    }
    
    // 复制剩余元素
    while (i < n1) arr[k++] = L[i++];
    while (j < n2) arr[k++] = R[j++];
}

// 归并排序主函数
void merge_sort(vector<int>& arr, int left, int right) {
    if (left < right) {
        int mid = left + (right - left) / 2; // 避免溢出
        merge_sort(arr, left, mid);       // 左子数组排序
        merge_sort(arr, mid + 1, right);  // 右子数组排序
        merge(arr, left, mid, right);     // 合并两个有序子数组
    }
}

2. 快速排序(不稳定排序,平均O(n log n))

#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>
using namespace std;

// 分区函数:选择最右侧元素作为基准,返回基准的最终位置
int partition(vector<int>& arr, int low, int high) {
    int pivot = arr[high]; // 基准元素
    int i = low - 1;       // i指向小于基准区域的末尾
    
    for (int j = low; j < high; ++j) {
        if (arr[j] <= pivot) { // 小于等于基准的元素移入左侧区域
            i++;
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i + 1], arr[high]); // 基准元素放到最终位置
    return i + 1;
}

// 随机分区(优化有序数组的最坏情况)
int random_partition(vector<int>& arr, int low, int high) {
    srand((unsigned int)time(NULL));
    int rand_idx = low + rand() % (high - low + 1); // 随机选择基准索引
    swap(arr[rand_idx], arr[high]);                // 基准移到末尾
    return partition(arr, low, high);
}

// 快速排序主函数(优化版)
void quick_sort(vector<int>& arr, int low, int high) {
    if (low < high) {
        int pi = random_partition(arr, low, high); // 分区
        quick_sort(arr, low, pi - 1);            // 左子数组排序
        quick_sort(arr, pi + 1, high);           // 右子数组排序
    }
}

3. 最大子数组和(分治实现,O(n log n))

#include <vector>
#include <climits>
#include <algorithm>
using namespace std;

// 计算跨中间点的最大子数组和
int cross_max(vector<int>& nums, int left, int mid, int right) {
    // 左半部分最大和(从mid向左扩展)
    int left_max = INT_MIN;
    int sum = 0;
    for (int i = mid; i >= left; --i) {
        sum += nums[i];
        left_max = max(left_max, sum);
    }
    
    // 右半部分最大和(从mid+1向右扩展)
    int right_max = INT_MIN;
    sum = 0;
    for (int i = mid + 1; i <= right; ++i) {
        sum += nums[i];
        right_max = max(right_max, sum);
    }
    
    return left_max + right_max;
}

// 分治求解最大子数组和
int max_subarray(vector<int>& nums, int left, int right) {
    if (left == right) return nums[left]; // 递归终止条件:单个元素
    
    int mid = left + (right - left) / 2;
    int left_max = max_subarray(nums, left, mid);       // 左子数组最大和
    int right_max = max_subarray(nums, mid + 1, right); // 右子数组最大和
    int cross = cross_max(nums, left, mid, right);     // 跨中间点最大和
    
    return max({left_max, right_max, cross}); // 返回三者最大值
}

// 对外接口
int max_subarray_sum(vector<int>& nums) {
    if (nums.empty()) return 0;
    return max_subarray(nums, 0, nums.size() - 1);
}

八、递归算法

1. 斐波那契数列(递归+记忆化优化)

#include <vector>
using namespace std;

// 记忆化递归:避免重复计算
long long fib_memo(int n, vector<long long>& memo) {
    if (n <= 1) return n;
    if (memo[n] != -1) return memo[n]; // 已计算过直接返回
    memo[n] = fib_memo(n - 1, memo) + fib_memo(n - 2, memo);
    return memo[n];
}

// 对外接口
long long fibonacci(int n) {
    if (n < 0) return 0;
    vector<long long> memo(n + 1, -1); // 记忆化数组
    return fib_memo(n, memo);
}

2. 汉诺塔问题(递归实现)

#include <iostream>
#include <string>
using namespace std;

// 将n个圆盘从A柱通过B柱移动到C柱
void hanoi(string A, string B, string C, int n) {
    if (n == 1) {
        // 递归终止:1个圆盘直接移动
        cout << A << "->" << C << endl;
        return;
    }
    hanoi(A, C, B, n - 1);    // 把n-1个圆盘从A移到B(借助C)
    cout << A << "->" << C << endl; // 把第n个圆盘从A移到C
    hanoi(B, A, C, n - 1);    // 把n-1个圆盘从B移到C(借助A)
}

3. 字符串反转(递归实现)

#include <string>
using namespace std;

string reverse_string(string s) {
    if (s.length() <= 1) return s; // 递归终止:空串或单个字符
    // 取最后一个字符 + 剩余子串的反转
    return s.back() + reverse_string(s.substr(0, s.length() - 1));
}

4. 阶乘计算(递归实现)

// 递归计算n的阶乘(n >= 0)
long long factorial(int n) {
    if (n == 0 || n == 1) return 1; // 递归终止条件
    return n * factorial(n - 1);   // 递归表达式
}

九、算法复杂度相关(辅助工具)

1. 复杂度估算辅助函数(统计基本操作次数)

#include <iostream>
using namespace std;

// 统计冒泡排序的基本操作次数(交换+比较)
pair<int, int> bubble_sort_count(vector<int>& arr) {
    int n = arr.size();
    int compare_cnt = 0; // 比较次数
    int swap_cnt = 0;    // 交换次数
    
    for (int i = 0; i < n - 1; ++i) {
        bool flag = false;
        for (int j = 0; j < n - 1 - i; ++j) {
            compare_cnt++;
            if (arr[j] > arr[j + 1]) {
                swap(arr[j], arr[j + 1]);
                swap_cnt++;
                flag = true;
            }
        }
        if (!flag) break; // 无交换说明已有序
    }
    return {compare_cnt, swap_cnt};
}

// 统计二分查找的比较次数
int binary_search_count(vector<int>& nums, int target) {
    int left = 0, right = nums.size() - 1;
    int compare_cnt = 0;
    while (left <= right) {
        compare_cnt++;
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) return compare_cnt;
        else if (nums[mid] < target) left = mid + 1;
        else right = mid - 1;
    }
    return compare_cnt; // 未找到也返回比较次数
}

2. 常见复杂度对比工具(生成测试数据)

#include <vector>
#include <random>
using namespace std;

// 生成随机数组
vector<int> generate_random_array(int n, int min_val, int max_val) {
    vector<int> arr(n);
    random_device rd;
    mt19937 gen(rd());
    uniform_int_distribution<> dis(min_val, max_val);
    for (int i = 0; i < n; ++i) {
        arr[i] = dis(gen);
    }
    return arr;
}

// 生成有序数组(升序)
vector<int> generate_sorted_array(int n, int start = 1) {
    vector<int> arr(n);
    for (int i = 0; i < n; ++i) {
        arr[i] = start + i;
    }
    return arr;
}

// 生成逆序数组
vector<int> generate_reverse_sorted_array(int n, int end = 1000) {
    vector<int> arr(n);
    for (int i = 0; i < n; ++i) {
        arr[i] = end - i;
    }
    return arr;
}
posted @ 2025-12-21 08:53  kkman2000  阅读(1)  评论(0)    收藏  举报