内存碎片整理

【问题描述】
由于频繁的内存申请和释放,会产生大量的内存碎片,假设用链表管理内存的分配与回收,要求实现对存在内存碎片内存进行整理,将不连续的已释放的内存合并成大块内存。
(要求在原链表上操作)
管理内存的节点定义如下:
Struct Node
{
lnt length: //内存大小
lnt flag:1 //1 表示被占用,0 表示已释放 Struct Node*next;
}
【输入形式】
输入第一行为整数 n,表示要输入 n 对数; 第二行输入 n 对整,每一对数字中,第一个为内存大小,第二个为是占用还是释放。
例如:
23 1 21 0,输入了两对数字,第一对表示内存大小为 23,被占用,第二对表示内存大小21,已经释放。
【输出形式】
对内存碎片进行整理后的管理链表
【样例输入】
5
12 0 23 1 10 0 30 1 11 0
#include <stdio.h>
#include <stdlib.h>

// 定义内存管理节点结构体
struct Node {
    int length;      // 内存块大小
    int flag;        // 状态标记(1:占用 0:释放)
    struct Node* next; // 指向下一个节点的指针
};

int main() {
    int n;
    scanf("%d", &n);  // 读取输入的节点数量
    
    struct Node* head = NULL;         // 链表头指针初始化为空
    struct Node** current_ptr = &head; // 使用二级指针辅助构建链表
    
    // 第一阶段:构建初始链表
    for (int i = 0; i < n; ++i) {
        int length, flag;
        scanf("%d %d", &length, &flag);  // 读取每个节点的数据
        
        // 动态创建新节点
        struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
        new_node->length = length;
        new_node->flag = flag;
        new_node->next = NULL;
        
        // 将新节点接入链表(精妙的二级指针操作)
        *current_ptr = new_node;          // 当前指针指向的位置写入新节点地址
        current_ptr = &(new_node->next);  // 移动二级指针到新节点的next字段地址
    }

    // 第二阶段:合并相邻空闲内存块
    struct Node* current = head;  // 从链表头开始遍历
    while (current != NULL) {
        if (current->flag == 0) {  // 发现空闲块时启动合并流程
            struct Node* runner = current->next;  // 创建游标指针用于连续检测
            
            // 合并所有后续连续的空闲块
            while (runner != NULL && runner->flag == 0) {
                current->length += runner->length;  // 累加内存大小
                current->next = runner->next;       // 跳过被合并的节点
                
                // 释放被合并节点的内存
                struct Node* temp = runner;
                runner = runner->next;  // 游标移动到下一个待检测节点
                free(temp);
            }
        }
        current = current->next;  // 移动到下一个节点(可能是合并后的新next)
    }

    // 第三阶段:输出整理后的链表
    struct Node* output = head;
    while (output != NULL) {
        printf("%d %d ", output->length, output->flag);  // 格式:长度 状态
        output = output->next;
    }
    printf("\n");  // 输出结束换行

    // 第四阶段:释放链表内存(防止内存泄漏)
    while (head != NULL) {
        struct Node* temp = head;  // 保存当前节点指针
        head = head->next;          // 头指针前移
        free(temp);                 // 释放当前节点内存
    }

    return 0;
}
1. 二级指针构建链表技巧:
   - current_ptr初始指向head的地址
   - *current_ptr = new_node 相当于 head = new_node(首次)或前一个节点的next赋值(后续)
   - current_ptr = &(new_node->next) 将指针移动到新节点的next字段地址
   - 这种写法无需单独处理头节点,实现优雅的链表构建

2. 合并算法优化点:
   - 时间复杂度O(n):只需单次遍历,遇到空闲块时合并后续连续空闲块
   - 原地修改:直接在原链表上操作,不需要额外空间
   - 内存安全:及时释放被合并节点的内存

3. 边界条件处理:
   - 处理链表尾部的连续空闲块
   - 处理单个孤立空闲块的情况
   - 正确处理全占用链表的特殊情况

4. 内存管理完整性:
   - 输入时使用malloc分配内存
   - 合并时及时free被合并节点
   - 最后统一释放整个链表
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值