动态存储管理

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;
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值