You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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的执行逻辑:

  1. 所有进程先按到达时间升序排序;
  2. 在当前时间点,从已到达且未执行的进程中,选择执行时间(burst time)最长的进程;
  3. 执行该进程直到完成,更新当前时间为该进程的完成时间;
  4. 重复步骤2-3,直到所有进程执行完毕;
  5. 计算每个进程的等待时间、周转时间等指标。

优化你的排序代码

你手写的冒泡排序可以优化,且用独立数组存储进程信息容易出错,建议用结构体封装进程数据,再用标准库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;
}

对你当前阶段的建议

  1. 把独立的pid、arrivalTime数组改成结构体,避免数据同步错误;
  2. 用qsort代替手写冒泡排序,提升效率且代码更简洁;
  3. 调度循环中要处理「当前无进程到达」的情况,避免死循环;
  4. 执行完进程后及时计算并存储完成时间、等待时间等指标,方便后续统计。

内容的提问来源于stack exchange,提问作者Akhilesh Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:11:21