如何在C语言中对数组分组?非抢占式LJF调度器实现疑问
关于C语言数组分组与非抢占式LJF调度器实现的解答
一、C语言中数组数据的分组方法
数组分组的核心是先明确分组规则(比如奇偶、数值范围、自定义条件),再通过「统计数量→分配内存→填充分组」的步骤实现。下面举两个常见场景的示例:
1. 按奇偶性分组
把数组元素拆分为偶数和奇数两组:
#include <stdio.h> #include <stdlib.h> // 按奇偶分组,输出两组数组及其大小 void groupByParity(int arr[], int size, int **evenGroup, int *evenCount, int **oddGroup, int *oddCount) { // 第一步:统计两组元素数量 *evenCount = 0; *oddCount = 0; for (int i = 0; i < size; i++) { arr[i] % 2 == 0 ? (*evenCount)++ : (*oddCount)++; } // 第二步:为两组分配内存 *evenGroup = (int *)malloc(sizeof(int) * (*evenCount)); *oddGroup = (int *)malloc(sizeof(int) * (*oddCount)); if (*evenGroup == NULL || *oddGroup == NULL) { printf("内存分配失败\n"); exit(1); } // 第三步:遍历原数组,填充分组 int evenIdx = 0, oddIdx = 0; for (int i = 0; i < size; i++) { if (arr[i] % 2 == 0) { (*evenGroup)[evenIdx++] = arr[i]; } else { (*oddGroup)[oddIdx++] = arr[i]; } } } int main() { int sampleArr[] = {3, 7, 2, 9, 4, 10, 5}; int arrSize = sizeof(sampleArr) / sizeof(sampleArr[0]); int *evens, *odds; int evenNum, oddNum; groupByParity(sampleArr, arrSize, &evens, &evenNum, &odds, &oddNum); printf("偶数组:"); for (int i = 0; i < evenNum; i++) { printf("%d ", evens[i]); } printf("\n奇数组:"); for (int i = 0; i < oddNum; i++) { printf("%d ", odds[i]); } // 释放动态分配的内存 free(evens); free(odds); return 0; }
2. 按数值范围分组(0-5、6-10、11+)
只需修改统计和填充的条件,即可适配自定义范围:
#include <stdio.h> #include <stdlib.h> void groupByRange(int arr[], int size, int **lowGroup, int *lowCount, int **midGroup, int *midCount, int **highGroup, int *highCount) { *lowCount = 0; *midCount = 0; *highCount = 0; // 统计各范围元素数量 for (int i = 0; i < size; i++) { if (arr[i] <= 5) (*lowCount)++; else if (arr[i] <= 10) (*midCount)++; else (*highCount)++; } // 分配内存 *lowGroup = malloc(sizeof(int)*(*lowCount)); *midGroup = malloc(sizeof(int)*(*midCount)); *highGroup = malloc(sizeof(int)*(*highCount)); // 填充分组 int lIdx=0, mIdx=0, hIdx=0; for(int i=0; i<size; i++){ if(arr[i] <=5) (*lowGroup)[lIdx++] = arr[i]; else if(arr[i] <=10) (*midGroup)[mIdx++] = arr[i]; else (*highGroup)[hIdx++] = arr[i]; } }
二、非抢占式最长作业优先(LJF)调度器的完整实现
你已经完成了「按到达时间排序」的关键第一步,接下来我会从思路到代码帮你补全实现:
核心思路
非抢占式LJF的执行逻辑:
- 所有进程先按到达时间升序排序;
- 在当前时间点,从已到达且未执行的进程中,选择执行时间(burst time)最长的进程;
- 执行该进程直到完成,更新当前时间为该进程的完成时间;
- 重复步骤2-3,直到所有进程执行完毕;
- 计算每个进程的等待时间、周转时间等指标。
优化你的排序代码
你手写的冒泡排序可以优化,且用独立数组存储进程信息容易出错,建议用结构体封装进程数据,再用标准库qsort函数排序(效率更高、代码更简洁):
#include <stdio.h> #include <stdlib.h> // 封装进程所有信息的结构体 typedef struct { int pid; // 进程ID int arrivalTime; // 到达时间 int burstTime; // 执行时间 int completionTime; // 完成时间 int waitingTime; // 等待时间 int turnaroundTime; // 周转时间 } Process; // qsort的比较函数:按到达时间升序排序 int compareByArrival(const void *a, const void *b) { Process *p1 = (Process *)a; Process *p2 = (Process *)b; return p1->arrivalTime - p2->arrivalTime; }
完整调度实现代码
void scheduleLJF(Process processes[], int noOfProcesses) { int currentTime = 0; int completed = 0; int isCompleted[noOfProcesses]; // 初始化所有进程为未完成状态 for (int i = 0; i < noOfProcesses; i++) { isCompleted[i] = 0; } while (completed < noOfProcesses) { // 找到当前可执行进程中burst time最长的那个 int selectedIdx = -1; int maxBurst = -1; for (int i = 0; i < noOfProcesses; i++) { if (processes[i].arrivalTime <= currentTime && !isCompleted[i]) { if (processes[i].burstTime > maxBurst) { maxBurst = processes[i].burstTime; selectedIdx = i; } } } // 处理当前无进程到达的情况:跳到下一个进程的到达时间 if (selectedIdx == -1) { currentTime++; continue; } // 执行选中的进程 currentTime += processes[selectedIdx].burstTime; processes[selectedIdx].completionTime = currentTime; // 计算等待时间:完成时间 - 到达时间 - 执行时间 processes[selectedIdx].waitingTime = processes[selectedIdx].completionTime - processes[selectedIdx].arrivalTime - processes[selectedIdx].burstTime; // 计算周转时间:完成时间 - 到达时间 processes[selectedIdx].turnaroundTime = processes[selectedIdx].completionTime - processes[selectedIdx].arrivalTime; // 标记进程为已完成 isCompleted[selectedIdx] = 1; completed++; } } // 打印调度结果 void printSchedule(Process processes[], int noOfProcesses) { printf("PID\t到达时间\t执行时间\t完成时间\t等待时间\t周转时间\n"); for (int i = 0; i < noOfProcesses; i++) { printf("%d\t%d\t\t%d\t\t%d\t\t%d\t\t%d\n", processes[i].pid, processes[i].arrivalTime, processes[i].burstTime, processes[i].completionTime, processes[i].waitingTime, processes[i].turnaroundTime); } // 计算平均指标 float avgWaiting = 0, avgTurnaround = 0; for(int i=0; i<noOfProcesses; i++){ avgWaiting += processes[i].waitingTime; avgTurnaround += processes[i].turnaroundTime; } printf("\n平均等待时间:%.2f\n", avgWaiting/noOfProcesses); printf("平均周转时间:%.2f\n", avgTurnaround/noOfProcesses); } int main() { // 示例进程数据 Process processes[] = { {1, 0, 8}, {2, 1, 4}, {3, 2, 9}, {4, 3, 5} }; int noOfProcesses = sizeof(processes)/sizeof(processes[0]); // 按到达时间排序 qsort(processes, noOfProcesses, sizeof(Process), compareByArrival); // 执行LJF调度 scheduleLJF(processes, noOfProcesses); // 打印结果 printSchedule(processes, noOfProcesses); return 0; }
对你当前阶段的建议
- 把独立的pid、arrivalTime数组改成结构体,避免数据同步错误;
- 用
qsort代替手写冒泡排序,提升效率且代码更简洁; - 调度循环中要处理「当前无进程到达」的情况,避免死循环;
- 执行完进程后及时计算并存储完成时间、等待时间等指标,方便后续统计。
内容的提问来源于stack exchange,提问作者Akhilesh Sharma
相关产品推荐
相关产品推荐

