💡 【教材】 ▲08 动态存储管理

This commit is contained in:
康建伟
2018-01-09 22:14:14 +08:00
parent 3c678d18e5
commit adb9ac9e9e
12 changed files with 1079 additions and 0 deletions

View File

@@ -0,0 +1,90 @@
/************************************
* *
* 文件夹: ▲08 动态存储管理 *
* *
* 文件名: BoundaryTagMethod-main.c *
* *
* 内 容: 边界标识法相关函数测试 *
* *
************************************/
#include <stdio.h>
#include "BoundaryTagMethod.c" //**▲08 动态存储管理**//
int main(int argc, char *argv[])
{
WORD_a memory[MAX];
Space pav;
Space p1, p2, p3, p4;
printf("▼1、4\n▲函数 InitSpace_a等 测试...\n"); //1、4.函数InitSpace_a、PrintLayout_a测试
{
printf("初始化一个内存块 ");
InitSpace_a(memory);
pav = av;
PrintLayout_a(av, pav);
printf("\n");
}
PressEnter;
printf("▼2\n▲函数 AllocBoundTag 测试...\n"); //2.函数AllocBoundTag测试
{
printf("申请大小为 100 的内存块 p1 后...\n");
p1 = AllocBoundTag(&pav, 100);
PrintLayout_a(av, pav);
printf("\n");
}
PressEnter;
printf("申请大小为 600 的内存块 p2 后...\n");
{
p2 = AllocBoundTag(&pav, 600);
PrintLayout_a(av, pav);
printf("\n");
}
PressEnter;
printf("申请大小为 200 的内存块 p3 后...\n");
{
p3 = AllocBoundTag(&pav, 200);
PrintLayout_a(av, pav);
printf("\n");
}
PressEnter;
printf("▼3\n▲函数 Reclaim_a 测试...\n"); //3.函数Reclaim_a测试
{
printf("回收大小为 600 的内存块 p2 后...\n");
Reclaim_a(&pav, &p2);
PrintLayout_a(av, pav);
printf("\n");
}
PressEnter;
printf("申请大小为 400 的内存块 p4 后...\n");
{
p4 = AllocBoundTag(&pav, 400);
PrintLayout_a(av, pav);
printf("\n");
}
PressEnter;
printf("回收大小为 100 的内存块 p1 后...\n");
{
Reclaim_a(&pav, &p1);
PrintLayout_a(av, pav);
printf("\n");
}
PressEnter;
printf("回收大小为 400 的内存块 p4 后...\n");
{
Reclaim_a(&pav, &p4);
PrintLayout_a(av, pav);
printf("\n");
}
PressEnter;
return 0;
}

View File

@@ -0,0 +1,167 @@
/*******************************
* *
* 文件夹: ▲08 动态存储管理 *
* *
* 文件名: BoundaryTagMethod.c *
* *
* 算 法: 8.1 *
* *
*******************************/
#ifndef BOUNDARYTAGMETHOD_C
#define BOUNDARYTAGMETHOD_C
#include "BoundaryTagMethod.h" //**▲08 动态存储管理**//
void InitSpace_a(WORD_a memory[MAX+2])
{
Space pav;
pav = &memory[0];
memory[0].Ptr.llink = pav;
memory[0].tag = 0;
memory[0].size = MAX;
memory[0].rlink = pav;
memory[MAX-1].Ptr.uplink = pav;
memory[MAX-1].tag = 0;
av = pav;
}
/*════╗
║ 算法8.1║
╚════*/
Space AllocBoundTag(Space *pav, int n) //请求分配n个字
{
Space p, f;
for(p=*pav; p && p->size<n && p->rlink!=*pav; p=p->rlink)
; //查找不小于n的空闲块
if(!p || p->size<n)
return NULL; //找不到合适的空闲块
else
{ //寻找到不小于n的空闲块
f = FootLoc(p); //指向此空闲块的底部
*pav = p->rlink; //pav指向p结点的后继结点
if(p->size-n<=E) //整块分配,忽略<=E的剩余量
{
if(*pav==p) //只有一个块
*pav = NULL; //被占用后可利用表变为空表
else //在表中删除分配的结点
{
(*pav)->Ptr.llink = p->Ptr.llink;
p->Ptr.llink->rlink = *pav;
}
p->tag = f->tag = 1; //设占用块标志为1
}
else //从中间切割,占用后面的部分
{
f->tag = 1; //修改分配块的底部标志
p->size -= n; //置剩余块大小
f = FootLoc(p); //指向剩余块底部
f->tag = 0; //设置剩余块底部标志
f->Ptr.uplink = p;
p = f + 1; //指向分配块头部
p->tag = 1; //设置分配块头部
p->size = n;
}
return p; //p结点的llink和rlink域并未改变这对回收空间有用
}
}
void Reclaim_a(Space *pav, Space *p)
{
Space f, s, t, q;
int l, r;
l = (*p - 1)->tag; //lr为指示释放块的左右邻块是否空闲
r = (*p + (*p)->size)->tag;
if(!(*pav)) //可利用空间表为空
{
*pav = (*p)->Ptr.llink = (*p)->rlink = *p; //修改空闲表指针
(*p)->tag = (FootLoc(*p))->tag = 0; //修改头尾标志
(FootLoc(*p))->Ptr.uplink = *p; //修改尾部域
}
else //可利用空间表不为空
{
if(l && r) //左右邻区均不为空
{
(*p)->tag = 0;
(FootLoc(*p))->Ptr.uplink = *p;
(FootLoc(*p))->tag = 0;
q = (*pav)->Ptr.llink;
(*p)->rlink = *pav;
(*p)->Ptr.llink = q;
q->rlink = (*pav)->Ptr.llink = *p;
*pav = *p; //令刚释放的结点为下次分配时的最先查询的结点
}
else if(!l && r) //左邻区为空,右邻区不为空
{
s = (*p - 1)->Ptr.uplink; //s指向左邻区空闲时的首地址
s->size += (*p)->size; //设置新空闲块大小
(FootLoc(*p))->Ptr.uplink = s; //设置新的空闲块底部
(FootLoc(*p))->tag = 0;
}
else if(l && !r) //左邻区不为空,右邻区为空
{
t = *p + (*p)->size; //t指向右邻区空闲时的首地址
(*p)->tag = 0; //p为合并后的结点头部地址
q = t->Ptr.llink; //此处q为右邻区的前驱结点首地址
(*p)->Ptr.llink = q; //链接q与p
q->rlink = *p;
q = t->rlink; //此处q为右邻区的后继结点首地址
(*p)->rlink = q; //链接q与p
q->Ptr.llink = *p;
(*p)->size += t->size; //新空闲块大小
(FootLoc(t))->Ptr.uplink = *p; //底部指针指向新结点的头部
if(*pav==t)
*pav = s;
}
else //左右邻区均为空
{
s = (*p - 1)->Ptr.uplink; //s指向左邻区空闲时的首地址
t = *p + (*p)->size; //t指向右邻区空闲时的首地址
s->size += (*p)->size + t->size; //设置新结点大小
t->Ptr.llink->rlink = t->rlink; //跨过t链接
t->rlink->Ptr.llink = t->Ptr.llink;
(FootLoc(t))->Ptr.uplink = s; //新结点底部指针指向其头部
if(*pav==t)
*pav = s;
}
}
*p = NULL;
}
void PrintLayout_a(Space av, Space pav)
{
Space r;
r = pav;
printf("空闲块起止范围:┃");
printf("%4d←→%4d┃", r-av+1, r+r->size-av);
while(r->rlink!=pav)
{
r = r->rlink;
printf("%4d←→%4d┃", r-av+1, r+r->size-av);
}
printf("\n");
}
#endif

View File

@@ -0,0 +1,61 @@
/*******************************
* *
* 文件夹: ▲08 动态存储管理 *
* *
* 文件名: BoundaryTagMethod.h *
* *
* 内 容: 边界标识法 *
* *
*******************************/
#ifndef BOUNDARYTAGMETHOD_H
#define BOUNDARYTAGMETHOD_H
#include <stdio.h>
#include "../../▲01 绪论/Status.h" //**▲01 绪论**//
/* 宏定义 */
#define MAX 1000
#define E 10 //分配空间时的正误差即分配空间最多比所需空间多E个字
#define FootLoc(p) p+(p)->size-1 //指向p所指结点的底部
/* 类型定义 */
typedef struct WORD_a //WORD_a内存字类型
{
union
{
struct WORD_a *llink; //头部域,指向前驱结点
struct WORD_a *uplink; //底部域,指向本结点头部
}Ptr;
int tag; //块标志0空闲1占用头部和尾部均有
int size; //头部域,块大小
struct WORD_a *rlink; //头部域,指向后继结点
}WORD_a;
typedef WORD_a* Space; //Space可利用空间指针类型
/* 全局变量 */
Space av; //整个内存块的起始地址
/* 边界标识法函数列表 */
void InitSpace_a(WORD_a memory[MAX+2]);
/*━━━━━━━━━━━━━┓
┃(01)初始化一块空闲内存块。┃
┗━━━━━━━━━━━━━*/
Space AllocBoundTag(Space *pav, int n);
/*━━━━━━━━━━━━━━━━━━━┓
┃(02)算法8.1:分配算法(首次拟合法)。 ┃
┗━━━━━━━━━━━━━━━━━━━*/
void Reclaim_a(Space *pav, Space *p);
/*━━━━━━━┓
┃(03)回收算法。┃
┗━━━━━━━*/
void PrintLayout_a(Space av, Space pav);
/*━━━━━━━━━━━━━━━━┓
┃(04)输出当前空闲内存块起止地址。┃
┗━━━━━━━━━━━━━━━━*/
#endif

View File

@@ -0,0 +1,96 @@
/********************************
* *
* 文件夹: ▲08 动态存储管理 *
* *
* 文件名: BuddySystem-main.c *
* *
* 内 容: 伙伴系统相关函数测试 *
* *
********************************/
#include <stdio.h>
#include "BuddySystem.c" //**▲08 动态存储管理**//
int main(int argc, char *argv[])
{
FreeList avail;
WORD_b *p1, *p2, *p3, *p4;
printf("▼1、5\n▲函数 InitSpace_b等 测试...\n"); //1、5.函数InitSpace_b、PrintLayout_b测试
{
printf("初始化一个内存块 ");
InitSpace_b(avail);
PrintLayout_b(avail);
printf("\n");
}
PressEnter;
printf("▼2\n▲函数 AllocBuddy 测试...\n"); //2.函数AllocBuddy测试
{
printf("申请大小为 1 的内存块 p1 后...\n");
p1 = AllocBuddy(avail, 1);
PrintLayout_b(avail);
printf("\n");
}
PressEnter;
printf("申请大小为 2 的内存块 p2 后...\n");
{
p2 = AllocBuddy(avail, 2);
PrintLayout_b(avail);
printf("\n");
}
PressEnter;
printf("申请大小为 3 的内存块 p3 后...\n");
{
p3 = AllocBuddy(avail, 3);
PrintLayout_b(avail);
printf("\n");
}
PressEnter;
printf("申请大小为 1 的内存块 p4 后...\n");
{
p4 = AllocBuddy(avail, 1);
PrintLayout_b(avail);
printf("\n");
}
PressEnter;
printf("▼3、4\n▲函数 Reclaim_b等 测试...\n"); //3、4.函数Buddy、Reclaim_b测试
{
printf("回收内存块 p1 后...\n");
Reclaim_b(avail, &p1);
PrintLayout_b(avail);
printf("\n");
}
PressEnter;
printf("回收内存块 p2 后...\n");
{
Reclaim_b(avail, &p2);
PrintLayout_b(avail);
printf("\n");
}
PressEnter;
printf("回收内存块 p3 后...\n");
{
Reclaim_b(avail, &p3);
PrintLayout_b(avail);
printf("\n");
}
PressEnter;
printf("回收内存块 p4 后...\n");
{
Reclaim_b(avail, &p4);
PrintLayout_b(avail);
printf("\n");
}
PressEnter;
return 0;
}

View File

@@ -0,0 +1,182 @@
/*****************************
* *
* 文件夹: ▲08 动态存储管理 *
* *
* 文件名: BuddySystem.c *
* *
* 算 法: 8.2 *
* *
*****************************/
#ifndef BUDDYSYSTEM_C
#define BUDDYSYSTEM_C
#include "BuddySystem.h" //**▲08 动态存储管理**//
void InitSpace_b(FreeList avail)
{
int k;
WORD_b *r;
for(k=0; k<=M; k++)
{
avail[k].nodesize = (int)pow(2, k);
avail[k].first = NULL;
}
r = (WORD_b *)malloc((int)pow(2, M)*sizeof(WORD_b));
if(!r)
exit(OVERFLOW);
r->llink = r->rlink = r;
r->tag = 0;
r->kval = M;
avail[M].first = r;
start = r;
end = r + avail[M].nodesize - 1;
}
/*════╗
║ 算法8.2║
╚════*/
WORD_b* AllocBuddy(FreeList avail, int n) //avail[0..m]为可利用空间表n为申请分配量
{ //包括标志在内分配n个内存
int k, i;
WORD_b *pa, *pre, *suc, *pi;
for(k=0; k<=M && (avail[k].nodesize<n || !avail[k].first); k++)
; //查找满足分配要求的子表
if(k>M)
return NULL; //分配失败返回NULL
else //进行分配
{
pa = avail[k].first; //指向可分配子表的第一个结点
pre = pa->llink; //分别指向前驱和后继
suc = pa->rlink;
if(pa==suc)
avail[k].first = NULL;
else
{
pre->rlink = suc;
suc->llink = pre;
avail[k].first = suc;
}
for(i=1; k-i>=0 && avail[k-i].nodesize>=n; i++)
{
pi = pa + (int)pow(2, k-i);
pi->rlink = pi;
pi->llink = pi;
pi->tag = 0;
pi->kval = k - i;
avail[k-i].first = pi;
}
pa->tag = 1;
pa->kval = k - (--i);
}
return pa;
}
WORD_b* Buddy(WORD_b* p) //start原始空闲块起点
{
int s, m, n;
s = p - start;
m = (int)pow(2, p->kval);
n = (int)pow(2, p->kval+1);
if(s%n==0)
return p + m;
if(s%n==m)
return p - m;
}
void Reclaim_b(FreeList avail, WORD_b** p)
{
WORD_b* s;
s = Buddy(*p); //s指向p的伙伴的地址
while(s>=start && s<=end && s->tag==0 && s->kval==(*p)->kval)
{
if(s->llink==s && s->rlink==s) //链表上仅此一个结点
avail[s->kval].first = NULL;
else
{
s->llink->rlink = s->rlink;
s->rlink->llink = s->llink;
if(avail[s->kval].first==s) //s是链表的首结点
avail[s->kval].first = s->rlink;
}
if((int)(*p-start)%(int)pow(2, (*p)->kval+1)==0) //p为前块
(*p)->kval++;
else
{
s->kval = (*p)->kval + 1;
*p = s;
}
s = Buddy(*p);
}
(*p)->tag = 0;
if(avail[(*p)->kval].first==NULL)
avail[(*p)->kval].first = (*p)->llink = (*p)->rlink = *p;
else
{
(*p)->rlink = avail[(*p)->kval].first;
(*p)->llink = (*p)->rlink->llink;
(*p)->rlink->llink = *p;
(*p)->llink->rlink = *p;
avail[(*p)->kval].first = *p;
}
*p = NULL;
}
void PrintLayout_b(FreeList avail)
{
int k;
WORD_b *r;
int mark;
for(k=0,mark=0; k<=M; k++) //判断内存是否被占满
{
if(avail[k].first)
{
mark = 1;
break;
}
}
if(!mark)
printf("内存已被占满!");
else
{
printf("空闲块起止范围:");
for(k=0; k<=M; k++)
{
r = avail[k].first;
if(r)
{
printf("┃%d←→%d", r-start+1, r+(int)pow(2, r->kval)-start);
while(r->rlink!=avail[k].first)
{
r = r->rlink;
printf("┃%d←→%d", r-start+1, r+(int)pow(2, r->kval)-start);
}
}
}
}
printf("\n");
}
#endif

View File

@@ -0,0 +1,65 @@
/*****************************
* *
* 文件夹: ▲08 动态存储管理 *
* *
* 文件名: BuddySystem.h *
* *
* 内 容: 伙伴系统 *
* *
*****************************/
#ifndef BUDDYSYSTEM_H
#define BUDDYSYSTEM_H
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "../../▲01 绪论/Status.h" //**▲01 绪论**//
/* 宏定义 */
#define M 3 //可利用空间总容量64k字的2的幂次子表的个数为M+1
/* 类型定义 */
typedef struct WORD_b
{
struct WORD_b *llink; //指向前驱结点
int tag; //块标志0空闲1占用
int kval; //块大小值为2的幂次k
struct WORD_b *rlink; //头部域,指向后继结点
}WORD_b; //WORD_b内存字类型结点的第一个字也称为head
typedef struct HeadNode
{
int nodesize; //该链表的空闲块的大小
WORD_b *first; //该链表的表头指针
}FreeList[M+1]; //表头向量类型
/* 全局变量 */
WORD_b *start, *end; //内存起点和终点
/* 伙伴系统函数列表 */
void InitSpace_b(FreeList avail);
/*━━━━━━━━━━━━━┓
┃(01)初始化一块空闲内存块。┃
┗━━━━━━━━━━━━━*/
WORD_b* AllocBuddy(FreeList avail, int n);
/*━━━━━━━━━━━━┓
┃(02)算法8.2:分配算法。 ┃
┗━━━━━━━━━━━━*/
WORD_b* Buddy(WORD_b* p);
/*━━━━━━━━━━━━━━━━━━┓
┃(03)返回p处内存块的伙伴内存块地址。 ┃
┗━━━━━━━━━━━━━━━━━━*/
void Reclaim_b(FreeList avail, WORD_b** p);
/*━━━━━━━┓
┃(04)回收算法。┃
┗━━━━━━━*/
void PrintLayout_b(FreeList avail);
/*━━━━━━━━━━━━━━━━┓
┃(05)输出当前空闲内存块起止地址。┃
┗━━━━━━━━━━━━━━━━*/
#endif

View File

@@ -0,0 +1,73 @@
/************************************
* *
* 文件夹: ▲08 动态存储管理 *
* *
* 文件名: GarbageCollection-main.c *
* *
* 内 容: 无用单元搜集相关函数测试 *
* *
************************************/
#include <stdio.h>
#include "GarbageCollection.c" //**▲08 动态存储管理**//
/* 函数原型 */
void Traverse(GList L, void(Visit)(GList));
void print(GList L);
int main(int argc, char *argv[])
{
GList G;
printf("创建并输出广义表:");
{
SString S;
char *s = "((),(e),(a,(b,c,d)))";
StrAssign_Sq(S, s);
InitGList_GL_H_T(&G);
CreateGList_GL_H_T_1(&G, S);
Output_GL_H_T(G, Head);
printf("\n\n");
}
PressEnter;
printf("▼1\n▲函数 MakeList 测试...\n"); //1.函数MakeList测试
{
printf("访问前的标志状态...\n");
Traverse(G, print);
printf("\n");
MakeList(G);
PressEnter;
printf("访问后的标志状态...\n");
Traverse(G, print);
printf("\n");
}
PressEnter;
return 0;
}
void Traverse(GList L, void(Visit)(GList))
{
if(L)
{
Visit(L);
if(L->tag==List)
{
Traverse(L->Union.ptr.hp, Visit);
Traverse(L->Union.ptr.tp, Visit);
}
}
}
void print(GList L)
{
if(L->tag==Atom)
printf("mark = %d 原子结点:%c\n", L->mark, L->Union.atom);
else
printf("mark = %d 表结点\n", L->mark);
}

View File

@@ -0,0 +1,85 @@
/*******************************
* *
* 文件夹: ▲08 动态存储管理 *
* *
* 文件名: GarbageCollection.c *
* *
* 算 法: 8.3 *
* *
******************************/
#ifndef GARBAGECOLLECTION_C
#define GARBAGECOLLECTION_C
#include "GarbageCollection.h" //**▲08 动态存储管理**//
/*════╗
║ 算法8.3║
╚════*/
void MakeList(GList G)
{
GList t, p, q;
Status finished;
if(G && G->mark==0)
{
t = NULL; //t为p的母表
p = G;
finished = FALSE;
while(!finished)
{
while(p->mark==0)
{
p->mark = 1; //MakeHead(p)的细化
q = p->Union.ptr.hp; //q指向p的表头
if(q!=NULL && q->mark==0)
{
if(q->tag==Atom) //表头为原子结点
q->mark = 1;
else //继续遍历子表
{
p->Union.ptr.hp = t;
p->tag = Atom;
t = p;
p = q;
}
}
} //完成对表头的标记
q = p->Union.ptr.tp;
if(q!=NULL && q->mark==0) //继续遍历表尾
{
p->Union.ptr.tp = t;
t = p;
p = q;
}
else //BackTrack(finished)的细化
{
while(t && t->tag==List) //表结点,从表尾回溯
{
q = t;
t = q->Union.ptr.tp;
q->Union.ptr.tp = p;
p = q;
}
if(t==NULL) //结束
finished = TRUE;
else //从表头回溯
{
q = t;
t = q->Union.ptr.hp;
q->Union.ptr.hp = p;
p = q;
p->tag = List;
} //继续遍历表尾
}
}
}
}
#endif

View File

@@ -0,0 +1,24 @@
/*******************************
* *
* 文件夹: ▲08 动态存储管理 *
* *
* 文件名: GarbageCollection.h *
* *
* 内 容: 无用单元搜集 *
* *
******************************/
#ifndef GARBAGECOLLECTION_H
#define GARBAGECOLLECTION_H
#include <stdio.h>
#include "../../▲01 绪论/Status.h" //**▲01 绪论**//
#include "../../▲05 数组和广义表/05 GeneralizedList-H&T/GeneralizedList-H-T.c" //**▲05 数组和广义表**//
/* 无用单元收集函数列表 */
void MakeList(GList G);
/*━━━━━━━━━━━━━━━━━━━┓
┃(01)算法8.3:遍历广义表(不利用栈)。 ┃
┗━━━━━━━━━━━━━━━━━━━*/
#endif

View File

@@ -0,0 +1,80 @@
/************************************
* *
* 文件夹: ▲08 动态存储管理 *
* *
* 文件名: StorageCompacting-main.c *
* *
* 内 容: 存储紧缩相关函数测试 *
* *
************************************/
#include <stdio.h>
#include "StorageCompacting.c" //**▲08 动态存储管理**//
int main(int argc, char *argv[])
{
int *p1, *p4;
char *p2, *p5;
float *p3;
printf("▼1\n▲函数 InitMemory 测试...\n"); //1.函数InitMemory测试
{
printf("初始化一块大小为 %d 的内存...\n", MAX);
InitMemory(MAX);
printf("\n");
}
PressEnter;
printf("▼5\n▲函数 PrintLayout 测试...\n"); //5.函数PrintLayout测试
{
printf("输出当前内存分配情况...\n");
PrintLayout();
printf("\n");
}
PressEnter;
printf("▼2、3\n▲函数 MallocMemory、CompressMemory 测试...\n");//2、3.函数MallocMemory、CompressMemory测试
{
printf("申请大小为 %d 的内存块 p1...\n", 100*sizeof(int));
p1 = (int*)MallocMemory(100*sizeof(int));
PrintLayout();
printf("\n");
PressEnter;
printf("申请大小为 %d 的内存块 p2...\n", 100*sizeof(char));
p2 = (char*)MallocMemory(100*sizeof(char));
PrintLayout();
printf("\n");
PressEnter;
printf("申请大小为 %d 的内存块 p3...\n", 100*sizeof(float));
p3 = (float*)MallocMemory(100*sizeof(float));
PrintLayout();
printf("\n");
}
PressEnter;
printf("▼4\n▲函数 FreeMemory 测试...\n"); //4.函数FreeMemory测试
{
printf("释放 p2 指向的内存块...\n");
FreeMemory(p2);
PrintLayout();
printf("\n");
PressEnter;
printf("申请大小为 %d 的内存块 p5...\n", 200*sizeof(char));
p5 = (char*)MallocMemory(200*sizeof(char));
PrintLayout();
printf("\n");
PressEnter;
printf("申请大小为 %d 的内存块 p4...\n", sizeof(int));
p4 = (int*)MallocMemory(100*sizeof(int));
PrintLayout();
printf("\n");
}
PressEnter;
return 0;
}

View File

@@ -0,0 +1,98 @@
/*******************************
* *
* 文件夹: ▲08 动态存储管理 *
* *
* 文件名: StorageCompacting.c *
* *
*******************************/
#ifndef STORAGECOMPACTING_C
#define STORAGECOMPACTING_C
#include "StorageCompacting.h" //**▲08 动态存储管理**//
void InitMemory(int n)
{
void *p = malloc(n);
start = (int)p;
end = start + n - 1;
cur = start;
}
void* MallocMemory(int n)
{
void *p;
if(cur+n-1>end) //空间不够,进行压缩
cur = CompressMemory();
if(cur+n-1>end) //压缩后空间依然不够用
{
printf("内存已满,无法继续分配空间!\n");
return NULL;
}
else
{
p = (void*)cur;
Record[0].length++; //内存地址表中添加此记录
Record[Record[0].length].stadr = cur;
Record[Record[0].length].length = n;
cur += n;
}
return p;
}
void FreeMemory(void* ptr)
{
int i, j;
for(i=1; i<=Record[0].length; i++)
{
if(Record[i].stadr==(int)ptr) //内存地址表压缩
{
for(j=i; j<Record[0].length; j++)
Record[j] = Record[j+1];
Record[0].length--;
return;
}
}
}
int CompressMemory()
{
int p, q, k;
for(k=1,p=start; k<=Record[0].length&&Record[k].length; k++)
{
q = Record[k].stadr;
memmove((void*)p, (void*)q, Record[k].length); //移动数据
Record[k].stadr = p; //更新起点
p += Record[k].length;
}
return p;
}
void PrintLayout()
{
int k, count;
printf("已占用的内存块范围:┃");
for(k=1,count=0; k<=Record[0].length; k++)
{
printf("%3d←→%3d┃", Record[k].stadr-start, Record[k].stadr+Record[k].length-start-1);
count += Record[k].length;
}
printf("\n");
printf("内存已占用块数:%4d空闲块数%4d。\n", count, MAX-count);
}
#endif

View File

@@ -0,0 +1,58 @@
/*******************************
* *
* 文件夹: ▲08 动态存储管理 *
* *
* 文件名: StorageCompacting.h *
* *
* 内 容: 存储紧缩 *
* *
*******************************/
#ifndef STORAGECOMPACTING_H
#define STORAGECOMPACTING_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../../▲01 绪论/Status.h" //**▲01 绪论**//
/* 宏定义 */
#define MAX 1000
/* 全局变量 */
struct
{
int stadr; //当前内存块起始地址
int length; //当前内存块大小
}Record[MAX+1]; //内存地址表
int start, end; //空闲内存块下阕和上阕(固定)
int cur; //当前空闲内存块起点(浮动)
/* 存储紧缩函数列表 */
void InitMemory(int n);
/*━━━━━━━━━━━━━━━━━━━┓
┃(01)初始化一块大小为 n 的空闲内存块。 ┃
┗━━━━━━━━━━━━━━━━━━━*/
void* MallocMemory(int n);
/*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃(02)分配一块大小为 n 的空闲内存块,若分配成功,返回其地址。 ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
void FreeMemory(void* ptr);
/*━━━━━━━━━━━━━━━━━┓
┃(03)释放地址 ptr 处的空闲内存块。 ┃
┗━━━━━━━━━━━━━━━━━*/
int CompressMemory();
/*━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃(04)存储紧缩算法,返回压缩后空闲内存块当前起始地址。┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━*/
void PrintLayout();
/*━━━━━━━━━━━━━━━━━━━┓
┃(05)输出当前空闲、非空闲内存块的数量。┃
┗━━━━━━━━━━━━━━━━━━━*/
#endif