您的位置:首页 > 其它

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

2009-08-02 13:29 267 查看
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//头文件
#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");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: