用C 实现以静态数组作为内存池的单向链表

完全是ctrl c / v的new bing 吐出来的代码,看着还不错,按自己的想法补了点注释。


这是一个使用空闲链表技术优化后的单向链表实现,它使用静态数组作为内存池,而不是堆内存。它还包含一个有序插入函数,可以根据 data 的大小自动找到合适的插入位置,使整个链表保持从小到大的顺序。这个版本添加了一些注释,以帮助您更好地理解代码。请注意,这只是一个示例,您可能需要根据您的具体需求进行修改。

空闲链表:就是把内存池本身初始化成一个链表,每个节点对应一个空闲的块,创建新链表的节点时直接从空闲链表里拿,不用反复查找。几乎不用多付出空间成本,只是在内存池初始化时多费一点时间。

有序插入函数:就是在插入的时候把节点排好序,之后用起来方便。

代码

#include <stdio.h>
#include <stdbool.h>

#define POOL_SIZE 10

typedef struct Node {
    int data;
    struct Node *next;
} Node;

Node memory_pool[POOL_SIZE];   // 后续可以把内存池和head 节点包在一个结构体里面
Node *free_list = NULL;        //空闲链表的头节点

// 初始化内存池
void init_memory_pool() {
    for (int i = 0; i < POOL_SIZE; i++) {
        memory_pool[i].next = free_list;    //从末端节点开始逐步初始化空闲链表
        free_list = &memory_pool[i];
    }
}

// 从内存池中获取一个空闲节点
Node *get_node_from_pool() {
    if (free_list == NULL) {
        printf("Memory pool is full\n");
        return NULL;
    }
    Node *node = free_list;
    free_list = free_list->next;    // 空闲链表的节点存取都发生在头节点
    return node;
}

// 将节点返回到内存池中
void return_node_to_pool(Node *node) {
    node->next = free_list;
    free_list = node;
}

// 在链表头部插入一个新节点
void insert(Node **head, int data) {
    Node *new_node = get_node_from_pool();
    if (new_node == NULL) return;
    new_node->data = data;
    new_node->next = *head;
    *head = new_node;
}

// 按顺序插入一个新节点
void insert_sorted(Node **head, int data) {
    Node *new_node = get_node_from_pool();
    if (new_node == NULL) return;
    new_node->data = data;

    // 查找插入位置
    Node *current = *head, *prev = NULL;
    while (current != NULL && current->data < data) {    //找到一个比新节点大的节点,把新节点插在前面,实现从小到大排序
        prev = current;
        current = current->next;
    }
    // 插入新节点
    if (prev == NULL) {    // 表示head == NULL 或头部第一个节点就比新节点大,所以让head 指向新节点,新节点的next 是原来的head
        new_node->next = *head;
        *head = new_node;
    } else {    // prev 指向比新节点大的节点的前一个节点,所以就是要把新节点插进prev 和current 中间
        new_node->next = prev->next;    // 也可以写成 new_node->next = current;
        prev->next = new_node;
    }
}

// 删除一个节点
void delete(Node **head, int data) {
    Node *temp = *head, *prev;
    if (temp != NULL && temp->data == data) {
        *head = temp->next;
        return_node_to_pool(temp);
        return;
    }
    while (temp != NULL && temp->data != data) {
        prev = temp;
        temp = temp->next;
    }
    if (temp == NULL) return;
    prev->next = temp->next;
    return_node_to_pool(temp);
}

// 打印链表
void print_list(Node *node) {
    while (node != NULL) {
        printf("%d ", node->data);
        node = node->next;
    }
}

int main() {
    init_memory_pool();

    Node *head = NULL;

    insert_sorted(&head, 3);
    insert_sorted(&head, 1);
    insert_sorted(&head, 2);

    printf("Created linked list: ");
    print_list(head);

    delete(&head, 2);

    printf("\nLinked list after deletion: ");
    print_list(head);

    return 0;
}

P.S.

不知道这个版权该怎么算,懒得看巨硬的用户协议,既然我至少付出了复制粘贴 传达神谕的劳动,就算是原创吧 [doge]。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下载时请看下面说明,对写一个动态的内存池很有帮助。 这是一个用C++语言链表的方法实现的一个静态内存池代源码。原理就是先向系统申请一块大内存,然后把这一大块分隔成相等的很多小块,然后在这这些小块的首地址部份放一个结构体,结构体中有一个值是用来标明这一小块是否使用中。在这里存放你要放存的数据就是用结构体首地址加结构体自身长度就得到要放数据的首地址了.具体看代码的实现吧。我说一下动态内存池的写法。那是我给公司写的就不能上传了。结构体和静态内存池的这个差不多一样,只是增加了一个成员用来记录每一节点到大块内存的首地址在到本节点的一个尺寸长度值,做法也是先申请一块大内存。我先从释放说起吧,释放本节点时看自己的相邻节点是不是有释放掉的,如果有则合并掉他们成为一个块,如果碰到相邻的节点是另外的一个大块的话就不用合并了,原因他和自己所在的这一个大块内存上物理地址不是连续,这里一定要记住,释放过程算法怎么去写就看你的了。下面是分配写法要考虑的。在分配一小块内存给高层使用时,如果是分配在尾节点去分配的情况,那好办啊,尾节点如果不够分配了就直接从系统去申请一块大内存,节点连起来在分配,这里有可能会浪费掉一小块以结构体大小的一块内存,如果够分配就直接分配了。如果是在中间节点去分配,这里就要将释放时合并的如果大于现在要分配的就拆开来用,如果拆开剩余的那一部份只有结构体大小就不用在拆开了。这些都是要考虑的东西,优化加快速度就看你自己了.可能看时不些不明白,看静态内存的写法后你就明白了.有时我也要下载其他人共享的东西,所以就一分吧.哈哈~~~~

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值