用哈希表加链表实现动态malloc

/
//头文件
#include <stdio.h>
#include <stdlib.h>
#define STEP 0    //可动态增加内存次数
#define MAXMEM 10000   //每次从系统获取内存字节数
#define HASHSIZE 100   //哈希表数组大小
#define NODESIZE sizeof(Node)  //链表节点字节数
typedef struct Node {
 char _state;   //内存状态
 size_t _size;   //内存大小
 struct Node *_prev;  //主链表前一节点地址
 struct Node *_next;  //主链表下一节点地址
 struct Node *_free;  //Free哈希表项中的下一节点地址
 struct Node *_used;  //Used哈希表项中的下一节点地址
} Node;
extern Node *usedHashTable[HASHSIZE]; //Used哈希表
extern Node *freeHashTable[HASHSIZE]; //Free哈希表
void *mini_malloc(size_t size);  //申请内存
void mini_free(void *addr);  //释放内存
 
/
//内存分配与释放调用mini_malloc与mini_free
#include "mini_malloc.h"
int initFlag = 0; //标识位,判断是否初始化分配内存
int step = 0;  //当前动态申请增加内存次数
Node *usedHashTable[HASHSIZE] = {NULL}; //占用空间哈希表
Node *freeHashTable[HASHSIZE] = {NULL}; //空闲空间哈希表
void insertMain(Node **head, Node **pNode, size_t fsize); //将新建内存块插入到主链表中
void insertFree(Node **pNode); //将空闲空间以空间从小到大排序方式插入到Free哈希表相应项中
void pushUsed(Node **pNode); //将占用空间插入到Used哈希表相应项最前面
void delFree(Node **pNode); //将指定空间从Free哈希表中删除
void delUsed(Node **pNode); //将指定空间从Used哈希表中删除
void delMain(Node **pNode); //将指定空间从主链表中删除
int init_malloc();  //初始化分配内存,返回该内存对应Free哈希表的key
void *find_malloc(Node *head, size_t size); //在指定的Free哈希表项中查找满足size大小的内存并返回相应的地址
int freeHash(size_t size); //生成并返回Free哈希表key
int usedHash(void *addr); //生成并返回Used哈希表key
int freeHash(size_t size) {
 return ((size - 1) / HASHSIZE) % HASHSIZE; //size-1确保1~100(101~200,201~300...)存放在Free哈希表同一项中
}
int usedHash(void *addr) {
 return ((int)addr) % HASHSIZE;
}  
///
初始化分配内存,返回该内存对应Free哈希表的key
int init_malloc() {
 Node *L = (Node *)((char *)malloc(MAXMEM)); //申请MAXMEM大小内存,从中创建一个节点
 int key = 0;
 L->_state = '/0';    //标识该内存状态为空闲
 L->_size = (size_t)(MAXMEM - NODESIZE);  //计算当前实际可用字节数
 key = freeHash(L->_size);   //生成该内存对应Free哈希表的key
 L->_prev = NULL;
 L->_next = NULL;
 L->_free = NULL;
 L->_used = NULL;
 insertFree(&L);     //将当前空闲内存插入到Free哈希表中
 return key;
}
///
在指定的Free哈希表项中查找满足size大小的内存并返回相应的地址
void *find_malloc(Node *head, size_t size) {
 size_t fsize = 0;
 while (head) {
  fsize = head->_size;   //获取当前可用内存fsize
  if (fsize >= size) {   //如果当前可用内存fsize满足用户需求size
   head->_state = '1';  //标识当前内存为占用
   pushUsed(&head);  //将当前占用的内存插入到Used哈希表中
   delFree(&head);   //奖当前占用的内存从Free哈希表中删除
   if (fsize - size > NODESIZE) { //如果当前可用内存fsize超过用户需求size并且剩余内存能够组织新内存块
    head->_size = size; //设置前面占用内存大小为用户需求size
    Node *pNode = (Node *)((char *)head + NODESIZE + size); //创建新内存块
    insertMain(&head, &pNode, fsize - size - NODESIZE);  //将新内存块插入到主链表中
    insertFree(&pNode); //将新空闲内存插入到Free哈希表中
   }
   return (void *)((char *)head + NODESIZE); //返回内存实际可用地址
  }
  head = head->_free;
 }
 return NULL;
}
///
申请内存
void *mini_malloc(size_t size) {
 if (size < 1 || size > MAXMEM - NODESIZE) {  //如果用户需求内存大小超过最大可用内存数,则返回NULL
  return NULL;
 }
 if (initFlag == 0) {   //如果未初始化内存
  init_malloc();
  initFlag = 1;
 }
 void *T;
 int key = freeHash(size);  //获取用户需求内存所在Free哈希表中的key
 while (1) {
  while (key < HASHSIZE) {
   T = find_malloc(freeHashTable[key], size); //在用户需求内存所在Free哈希表项中查找满足需求的内存
   if (T != NULL) { //如果在相应Free哈希表项中找到满足需求的内存,则返回它的地址
    return T;
   }
   ++key;  //当在相应Free哈希表项中未找到满足需求的内存,则查找下一项
  }
  //当在Free哈希表中没有找到满足需求的内存,并且当前动态申请增加内存次数小于设定次数,则新开辟一块内存
  if (step < STEP) {
   ++step;
   key = init_malloc();
  }
  else {
   return NULL;
  }
 }
 return NULL;
}
///
释放内存
void mini_free(void *addr) {
 int key = usedHash((void *)((char *)addr - NODESIZE)); //获取用户需释放内存对应的Used哈希表key
 Node *head = usedHashTable[key]; //获取用户需释放内存对应Used哈希表项
 while (head) {
  if ((Node *)((char *)addr - NODESIZE) == head) { //如果当前内存为用户需释放的内存
   head->_state = '/0';  //标识当前内存为空闲
   Node *pNode = head;
   delUsed(&head);
   //如果当前内存下一内存也为空闲,则合并它
   if (head->_next != NULL && head->_next->_state == '/0') {
    delFree(&(head->_next));
    delMain(&(head->_next));
   }
   //如果当前内存上一内存也为空闲,则合并它
   if (head->_prev != NULL && head->_prev->_state == '/0') {
    pNode = head->_prev;
    delFree(&pNode);
    delMain(&head);
   }
   insertFree(&pNode);
   return;
  }
  head = head->_used;
 }
}
///
将新建内存块插入到主链表中
void insertMain(Node **head, Node **pNode, size_t fsize) {
 if (*head == NULL || *pNode == NULL) {
  return;
 }
 (*pNode)->_state = '/0';
 (*pNode)->_size = fsize;
 (*pNode)->_prev = *head;
 (*pNode)->_next = NULL;
 (*pNode)->_free = NULL;
 (*pNode)->_used = NULL;
 if ((*head)->_next != NULL) {
  (*pNode)->_next = (*head)->_next;
  (*head)->_next->_prev = *pNode;
 }
 (*head)->_next = *pNode;
}
///
将空闲空间以空间从小到大排序方式插入到Free哈希表相应项中
void insertFree(Node **pNode) {
 if (*pNode == NULL)
  return;
 int key = freeHash((*pNode)->_size);
 Node *head = freeHashTable[key];
 if (head == NULL) {
  freeHashTable[key] = *pNode;
  freeHashTable[key]->_free = NULL;
  return;
 }
 Node *prev = NULL;
 while (head) {
  if (head->_size > (*pNode)->_size) {
   if (prev == NULL) {
    (*pNode)->_free = freeHashTable[key];
    freeHashTable[key] = *pNode;
   }
   else {
    (*pNode)->_free = head;
    prev->_free = *pNode;
   }
   return;
  }
  prev = head;
  head = head->_free;
 }
 prev->_free = *pNode;
 (*pNode)->_free = NULL;
}
///
将占用空间插入到Used哈希表相应项最前面
void pushUsed(Node **pNode) {
 if (*pNode == NULL)
  return;
 int key = usedHash((void *)(*pNode));
 Node *head = usedHashTable[key];
 if (head == NULL) {
  usedHashTable[key] = *pNode;
  usedHashTable[key]->_used = NULL;
 }
 else {
  (*pNode)->_used = usedHashTable[key];
  usedHashTable[key] = *pNode;
 }
}
///
将指定空间从Free哈希表中删除
void delFree(Node **pNode) {
 if (*pNode == NULL)
  return;
 int key = freeHash((*pNode)->_size);
 Node *head = freeHashTable[key];
 Node *prev = NULL;
 while (head) {
  if (head == *pNode) {
   if (prev != NULL) {
    if (head->_free != NULL) {
     prev->_free = head->_free;
    }
    else {
     prev->_free = NULL;
    }
   }
   else {
    if (head->_free != NULL) {
     freeHashTable[key] = head->_free;
    }
    else {
     freeHashTable[key] = NULL;
    }
   }
   return;
  }
  prev = head;
  head = head->_free;
 }
}
///
将指定空间从Used哈希表中删除
void delUsed(Node **pNode) {
 if (*pNode == NULL)
  return;
 int key = usedHash((void *)(*pNode));
 Node *head = usedHashTable[key];
 Node *prev = NULL;
 while (head) {
  if (head == *pNode) {
   if (prev != NULL) {
    if (head->_used != NULL) {
     prev->_used = head->_used;
    }
    else {
     prev->_used = NULL;
    }
   }
   else {
    if (head->_used != NULL) {
     usedHashTable[key] = head->_used;
    }
    else {
     usedHashTable[key] = NULL;
    }
   }
   return;
  }
  prev = head;
  head = head->_used;
 }
}
///
将指定空间从主链表中删除
void delMain(Node **pNode) {
 Node *T = *pNode;
 if (T == NULL)
  return;
 if (T->_prev != NULL) {
  T->_prev->_size = T->_prev->_size + T->_size + NODESIZE;
  if (T->_next != NULL) {
   T->_prev->_next = T->_next;
   T->_next->_prev = T->_prev;
  }
  else {
   T->_prev->_next = NULL;
  }
 }
 else {
  printf("ERROR./n");
 }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值