用哈希表加链表实现动态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");
}
}
//头文件
#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");
}
}
相关文章推荐
- 动态内存分配(malloc/free)简单实现--隐式空闲链表
- 用两个哈希表加链表实现malloc
- 查找算法集:顺序查找、二分查找、插值查找、动态查找(数组实现、链表实现)
- 数据结构学习---堆栈的动态数组实现及链表实现
- 动态可扩展哈希表的实现--第一集
- 利用数组和链表实现简单的哈希表
- 实现学生信息录入的动态长度控制(链表)
- C语言实现动态链表结构
- josephue约瑟夫环变种 单向链表实现 (可以更改使得游戏规则动态改变)
- 数据结构_队列_用链表动态建立释放节点实现队列各种操作_C++实现
- 动态内存分配及Malloc/free的实现
- 查找算法集:顺序查找、二分查找、插值查找、动态查找(数组实现、链表实现)
- 浅析动态内存分配及Malloc/free的实现
- 查找算法集:顺序查找、二分查找、插值查找、动态查找(数组实现、链表实现)
- 数据结构学习---堆栈的动态数组实现及链表实现
- 链表的C语言实现(含动态内存分配)
- 查找算法集:顺序查找、二分查找、插值查找、动态查找(数组实现、链表实现)
- C语言动态内存分配:(一)malloc/free的实现及malloc实际分配/释放的内存
- 查找算法集:顺序查找、二分查找、插值查找、动态查找(数组实现、链表实现)
- malloc实现动态数组的创建,数组个数由用户输入