c - 合并中的段错误 - 在 C 中排序
问题描述
我正在尝试使用归并排序对大小为 5500 的结构数组进行排序。但是,我很快就遇到了分段错误,因为我不允许使用 VLA。所以每次我递归地调用合并排序时,我都必须创建 2 个大小为 5500 的额外数组。
我希望能解决我的问题。我将在这里提供我的代码:
void merge(Student rightArr[], Student leftArr[], Student mergedArr[], int sizeOfRight, int sizeOfLeft) {
int rightArrIndex = 0;
int leftArrIndex = 0;
int mergedArrIndex = 0;
while (leftArrIndex < sizeOfLeft && rightArrIndex < sizeOfRight) {
char *ptrLeft, *ptrRight;
long gradeLeft = strtol(leftArr[leftArrIndex].grade, &ptrLeft, BASE_COUNT);
long gradeRight = strtol(rightArr[rightArrIndex].grade, &ptrRight, BASE_COUNT);
if (gradeLeft > gradeRight) {
mergedArr[mergedArrIndex] = rightArr[rightArrIndex];
rightArrIndex++;
} else {
mergedArr[mergedArrIndex] = leftArr[leftArrIndex];
leftArrIndex++;
}
mergedArrIndex++;
}
if (leftArrIndex == sizeOfLeft) {
for (int i = mergedArrIndex; i < (sizeOfLeft + sizeOfRight); i++) {
mergedArr[i] = rightArr[rightArrIndex];
rightArr++;
}
} else {
for (int i = mergedArrIndex; i < (sizeOfLeft + sizeOfRight); i++) {
mergedArr[i] = leftArr[leftArrIndex];
leftArr++;
}
}
}
void mergeSort(Student studentsArray[], int amountOfStudents) {
if (amountOfStudents <= 1) {
return;
}
int leftSize = (amountOfStudents / 2);
int rightSize = (amountOfStudents - leftSize);
Student leftArr[5500], rightArr[5500];
for (int i = 0; i < leftSize; i++) {
leftArr[i] = studentsArray[i];
}
for (int i = 0; i < rightSize; i++) {
rightArr[i] = studentsArray[i + leftSize];
}
mergeSort(leftArr, leftSize);
mergeSort(rightArr, rightSize);
merge(rightArr, leftArr, studentsArray, rightSize, leftSize);
}
解决方案
好的,我认为这应该做你想要的。它假设Student
并且BASE_COUNT
已经定义:
#include <stdlib.h>
#include <stdio.h>
void merge(Student studentsArr[],
int leftSize, int rightSize,
Student scratchArr[])
{
Student *leftArr = studentsArr;
Student *rightArr = studentsArr + leftSize;
int leftIx = 0, rightIx = 0, mergeIx = 0, ix;
while (leftIx < leftSize && rightIx < rightSize) {
long gradeLeft = strtol(leftArr[leftIx].grade, NULL, BASE_COUNT);
long gradeRight = strtol(rightArr[rightIx].grade, NULL, BASE_COUNT);
if (gradeLeft <= gradeRight) {
scratchArr[mergeIx++] = leftArr[leftIx++];
}
else {
scratchArr[mergeIx++] = rightArr[rightIx++];
}
}
while (leftIx < leftSize) {
scratchArr[mergeIx++] = leftArr[leftIx++];
}
// Copy the merged values from scratchArr back to studentsArr.
// The remaining values from rightArr (if any) are already in
// their proper place at the end of studentsArr, so we stop
// copying when we reach that point.
for (ix = 0; ix < mergeIx; ix++) {
studentsArr[ix] = scratchArr[ix];
}
}
void mergeSortInternal(Student studentsArray[],
int amountOfStudents,
Student scratchArr[])
{
if (amountOfStudents <= 1) {
return;
}
int leftSize = amountOfStudents / 2;
int rightSize = amountOfStudents - leftSize;
mergeSortInternal(studentsArray, leftSize, scratchArr);
mergeSortInternal(studentsArray + leftSize, rightSize, scratchArr);
merge(studentsArray, leftSize, rightSize, scratchArr);
}
#define MAX_ARR_SIZE 5500
void mergeSort(Student studentsArray[], int amountOfStudents)
{
if (amountOfStudents <= 1) {
return;
}
if (amountOfStudents > MAX_ARR_SIZE) {
fprintf(stderr, "Array too large to sort.\n");
return;
}
Student scratchArr[MAX_ARR_SIZE];
mergeSortInternal(studentsArray, amountOfStudents, scratchArr);
}
顶级排序函数是mergeSort
,如原始帖子中定义的那样。它声明了一个大小为 的临时数组MAX_ARR_SIZE
,定义为5500
。顶层函数本身不是递归的,所以这个临时数组只分配一次。
推荐阅读
- jenkins - 有没有办法在詹金斯管道中打印昨天的日期?
- sql - 子查询如何引用它之外的表?
- javascript - 将用户信息“位”更新为 true 时,angularjs 的更新代码不起作用
- javascript - 无法使用 e.target 获取父 div 类列表
- here-api - 按国家/地区请求交通事故数据?
- javascript - 我可以在节点 js 中修改来自 mysql 服务器的响应吗?
- angular - 想要拖动和替换元素而不是附加每个元素
- asp.net - ASP.NET CORE API 3.0 HTTP POST 不工作
- xamarin.forms - Xamarin Forms - 从选项卡式页面到其他屏幕并返回到选项卡式页面
- python - 如何通过 Google 目录 api 从 admin.google.com 获取所有移动设备的列表?