C++归并排序处理百万级数据崩溃问题排查及随机数疑问
归并排序处理大数据崩溃问题及rand()使用疑问
我编写的C归并排序代码可正常处理10万条int型数据,但处理100万、1000万条数据时会崩溃退出,使用DevC运行。请问代码存在什么问题?同时,当前通过rand()生成随机数的方式是否可用于其他排序算法?相关代码如下:
void merge(int arr[], int p, int q, int r) { int n1 = q - p + 1; int n2 = r - q; int L[n1], M[n2]; for (int i = 0; i < n1; i++) L[i] = arr[p + i]; for (int j = 0; j < n2; j++) M[j] = arr[q + 1 + j]; int i, j, k; i = 0; j = 0; k = p; while (i < n1 && j < n2) { if (L[i] <= M[j]) { arr[k] = L[i]; i++; } else { arr[k] = M[j]; j++; } k++; } while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = M[j]; j++; k++; } } void mergeSort(int arr[], int l, int r) { if (l < r) { int m = l + (r - l) / 2; mergeSort(arr, l, m); mergeSort(arr, m + 1, r); merge(arr, l, m, r); } } void printArray(int arr[], int size) { for (int i = 0; i < size; i++) cout << arr[i] << " "; cout << endl; } int main() { int n; cout << "Enter Number: "; cin >> n; int array[n]; for(int i = 0; i<n; i++) { array[i]=rand()%1000; } auto start2 = chrono::steady_clock::now(); mergeSort(array, 0, n - 1); auto end2 = chrono::steady_clock::now(); auto diff2 = end2 - start2; cout << "Time to sort for Merge: "<<chrono::duration <double, milli> (diff2).count() << " ms" << endl; return 0; }
一、代码崩溃的核心原因及修复方案
1. 栈溢出是主因
你的代码里有两处致命的栈内存滥用:
main函数中的int array[n];:这是变长数组,直接在栈上分配。栈的默认大小通常只有1~8MB,100万个int需要4MB(刚好踩线),1000万个int需要40MB,远超栈的容量,直接触发栈溢出崩溃。merge函数中的int L[n1], M[n2];:归并排序递归调用时,每个merge都会在栈上分配两个临时数组,递归层数叠加后,栈的占用会进一步飙升,加速崩溃。
另外补充:C标准里根本不支持变长数组,这是GCC的扩展特性,DevC用MinGW编译才允许,但这种写法本身就不标准,移植性差且风险极高。
2. 修复方案
把所有栈上的变长数组改成堆内存分配,推荐用C++的vector(自动管理内存,避免泄漏):
- 将
main里的int array[n];改为vector<int> array(n); - 将
merge里的int L[n1], M[n2];改为vector<int> L(n1), M(n2);
如果坚持用C风格写法,就用new/delete手动分配堆内存:
int* L = new int[n1]; int* M = new int[n2]; // ... 原有逻辑 ... delete[] L; delete[] M;
二、rand()生成随机数对其他排序算法的适用性
1. 可以用于大多数测试场景
你当前用rand()%1000生成0~999的重复随机数,完全可以用来测试冒泡、快速、插入、希尔等绝大多数排序算法:
- 能验证排序算法的正确性(是否能把乱序数组排好)
- 能测试算法的基本性能(对比不同算法的耗时)
2. 存在的局限性
- 随机数范围太小:如果要测试排序算法的最坏情况(比如快速排序的极端有序/逆序场景),
rand()%1000生成的重复值太多,无法模拟这种极端情况,需要调整生成逻辑(比如生成全范围int值,或者手动构造有序序列)。 - 随机性不足:
rand()的伪随机数周期短、质量一般,对于学术研究级别的性能对比,建议用C++11引入的<random>库(比如mt19937生成器),随机性更好,周期更长。 - 未初始化种子:当前代码没调用
srand(time(nullptr)),每次运行生成的随机数序列完全一样,若需要不同的测试序列,记得在main开头加上这句代码。
内容的提问来源于stack exchange,提问作者nima karami
相关产品推荐
相关产品推荐

