1.边界标识法
//BoundaryTagMethod.c
#include <stdio.h>
#include <stdlib.h>
//------------边界标识法---------------
typedef char OtherType;
typedef struct WORD{//WORD为内存字类型
union{
WORD *llink;//位于head区域,指向前驱结点
WORD *uplink;//位于foot区域,指向本结点
};
int tag;//块标识,0为空闲,1为占用,head区域和foot区域都有
int size;//位于head区域,标识块大小。
WORD *rlink;//位于head区域,指向后继结点
OtherType other;//字的其他部分
}WORD, head, foot, *Space;//*Space:可利用空间指针类型
#define FootLoc(p) p+p->size-1//指向p所指结点的底部
//data field
Space p,f;
int e;//常量e
//此函数用于分配空闲块
Space AllocBoundTag(Space pav, int n){
//若有不小于n的空闲块,则分配相应的存储块,并返回其首地址;否则,返回NULL
//若分配后可利用空间表不空,则pav指向表中刚分配过的结点的后继结点
for (p = pav; p&&p->size < n&&p->rlink != pav; p = p->rlink);//向后查找不小于n的空闲块
if (!p || p->size < n) return NULL;//找不到,返回空指针
else{ //找到了空闲块,并由p指向
f = FootLoc(p);//f指向结点foot区域
pav = p->rlink;//pav指向*p结点的后继结点
if (p->size - n <= e){//符合此条件,整块分配
if (pav == p)//p的后继结点就是它自己,将它分配出去,再无空闲结点
pav = NULL;
else{//在表中删除分配的结点
pav->llink = p->llink;
p->llink->rlink = pav;
}
p->tag = f->tag = 1;//修改分配结点的头部和底部标志
}
else{//分配该块的后n个字
f->tag = 1;//修改分配块的foot区域标识
p->size -= n;//置剩余块大小为n
f = FootLoc(p);//f指向剩余块foot区域
f->tag = 0;//修改剩余块foot区域tag
f->uplink = p;//修改剩余块foot区域uplink
p = f + 1;//p指向分配块head区域
p->tag = 1;//修改分配块head区域tag
p->size = n;//修改分配块head区域size
}
return p;
}
}
/*回收算法,共四种情况(阅读代码时参考课本图示)*/
//(1)释放块的左右邻区均为占用块
status release1(omit...){
p->tag = 0;
FootLoc(p)->uplink = p;
FootLoc(p)->tag = 0;
if (!pav)
pav = p->llink = p->rlink = p;
else{ //一个前插的过程
q = pav->llink;
p->rlink = pav;
p->llink = q;
q->rlink = pav->llink = p;
pav = p;//令刚释放的结点为下次分配时最先查询的结点
}
}
//(2)释放块的左邻区为空闲块,而右邻区为占用块
status release2(omit...){
n = p->size;//释放块的大小
s = (p - 1)->uplink;//左邻空闲块的头部地址
s->size += n;//设置新的空闲块的大小
//设置新的空闲块底部
f = p + n - 1;
f->uplink = s;
f->tag = 0;
}
//(3)释放块的右邻区为空闲块,左邻区为占用块
status release3(omit...){
t = p + p->size;//t是右邻空闲块的头部地址
p->tag = 0;//p为合并后的结点头部地址
q = t->llink;//q为*t结点在可利用空间表中的前驱结点的头部地址
p->llink = q; q->rlink = p;//q指向*p的前驱
q1 = t->rlink;//q1为*t结点在可利用空间表中的后继结点的头部地址
p->rlink = q1; q1->llink = p;//q1指向*p的后继
p->size += t->size;//新的空闲块的大小
FootLoc(t)->uplink = p;//底部指针指向新结点的头部
}
//(4)释放块的左右邻区均为空闲块
status release1(omit...){
n = p->size;//释放块的大小
s = (p - 1)->uplink;//s指向左邻块
t = p + p->size;//t指向右邻块
s->size += n + t->size;//设置新结点的大小
q = t->llink; q1 = t->rlink;
q->rlink = q1; q1->llink = q;//删去右邻空闲表结点
FootLoc(t)->uplink = s;//新结点底部指针指向其头部
}
2.伙伴系统
#include <stdio.h>
#include <stdlib.h>
#define m 16 //可利用空间总容量64K字的2的幂次,子表的个数为m+1
typedef struct WORD_b{
WORD_b *llink;//指向前驱结点
int tag;//块标识,0代表空闲。1代表占用
int kval;//块大小,值为2的幂次k
WORD_b *rlink;//头部域,指向后继结点
OtherType other;//字的其它部分
}WORD_b, head;//WORD内存字节类型。结点的第一个字是head
typedef struct HeadNode{//
int nodesize;//该链表的空闲块的大小
WORD_b *first;//该链表的表头指针
}FreeList[m + 1];//表头向量类型
//data field
int k,i;
WORD_b *pa,*pre,*suc;
//此函数分配空闲空间
WORD_b *AllocBuddy(FreeList avail, int n){
//avail[0...m]为可利用空间表,n为申请分配量。
//若有不小于n的空闲块,则分配相应的存储块,并返回其首地址;否则返回NULL
for (k = 0; k <= m && (avail[k].nodesize < n + 1 || !avail[k].first); k++);//查找满足分配要求的子表
if (k>m) return NULL;//分配失败,返回NULL
else{ //进行分配
pa = avail[k].first;//pa指向可分配子表的第一个结点
pre = pa->llink; suc = pa->rlink;//分别指向前驱和后继
if (pa == suc) avail[k].first = NULL;//分配后该子表变成空表
else{//从子表中删除*p结点
pre->rlink = suc;
suc->llink = pre;
avail[k].first = suc;
}
for (i = 1; avail[k - i].nodesize >= n + 1; i++){//将剩余块插入子表
pi = pa + pow(2, k - 1); pi->rlink = pi; pi->llink = pi;
pi->tag = 0; pi->kval = k - i; avail[k - 1].first = pi;
}
pa->tag = 1;
pa->kval = k - (--i);
}
return pa;
}
3.无用单元收集
#include <stdio.h>
#include <stdlib.h>
void MarkList(GList GL){
//遍历非空广义表GL(GL!=NULL且GL->mark==0),对表中所有未加标志的结点加标志。
t = NULL;//t记录当前结点的母表结点
p = GL;//p指向当前结点
finished = FALSE;
while (!finished){
while (p->mark == 0){
p->mark = 1;
//MarkHead(p)过程
q = p->p.hp;//q指向*p的表头
if (q&&q->mark == 0){
if (q->tag == 0) q->mark = 1;//表头为原子结点
else{//继续遍历子表
p->p.hp = t;
p->tag = 0;
t = p;
p = q;
}
}
}
q = p->p.tp;//q指向*p的表尾
if (q&&q->mark == 0){//继续遍历表尾
p->p.tp = t;
t = p;
p = q;
}//BackTrack(finished)的细化
else{
while (t&&t->tag == 1){//从表尾回溯
q = t;
t = q->p.tp;
q->p.tp;
p = q;
}
if (!t) finished = TRUE;//结束
else{//从表头回溯
q = t;
t = q->p.hp;
q->p.hp = p;
p = q;
p->tag = 1;
}
}
}
}