首先说明一下,这个程序可能还有隐藏的问题,但是我懒得改了。
对于此程序,有几点需要说明:
1.已分配区和空闲区是分别表示的
2.采用的是单向链表
3.采用了尾指针tail,单纯的用来指向尾空闲区域
4.写了3天,好吧,我确实很菜,但是引用请注明出处,谢谢了
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct progress
{
int id;//进程号
int size;// 大小
int start;//起始地址
struct progress *next;
}NODE;
NODE *head,*pnew,*frees,*tail;
NODE *head1,*pnew1,*frees1,*tail1;
int location=0;//用于指向尾部指针位置
int max=100;//定义分区的总大小
int rest=max;//尾空闲区的大小
void refresh();//紧凑技术
int first_fit(int sizes,int id);//循环首次适应算法
void insert(int size,int loc,int id);//已分配链表的插入
void create();//分配区的链表初始化
void create1();//创建空闲分区指针
void add();//已分配链表的添加
void add1(int size,int loc);//空闲链表的插入
void add2(int size,int location,NODE * t);//空闲链表的插入
void display();//输出
void pdelete();//已分配节点的回收
void refresh()//紧凑技术
{
//紧凑其实就是将已分配的链表进行挪动,设置一个大小变量用来记录当前位置,然后剩下的 就是重新创建
//采用空的两个链表进行重新创建
NODE *p,*t,*pnews,*tails,*heads,*q; //
int loca=0,n=1;//用于记录当前指针位置
rest=max;
t=(NODE *)malloc(sizeof(NODE));//
pnews=(NODE *)malloc(sizeof(NODE));//
tails=(NODE *)malloc(sizeof(NODE));//
heads=(NODE *)malloc(sizeof(NODE)); //创建头节点。
tails->next=NULL;
heads->next=tails;
for(p=head->next;p!=NULL;p=p->next) {
if(n==1){
tails->id=p->id; //新节点数据域存放输入的进程块号
tails->size=p->size;
tails->start=loca;
loca+=p->size;
tails->next=NULL;
n++;
}
else{
t->id=p->id; //新节点数据域存放输入的进程块号
t->size=p->size;
t->start=loca;
loca+=p->size;
t->next=NULL; //新节点指针域置NULL
tails->next=t;
tails=t;
}
rest-=p->size;
}
head=heads;
location=loca;
tail=tails;
//将空闲分区进行重置
tail1->next=NULL; //头节点指针域置NULL
head1->next=tail1; // 开始时尾指针指向头节点
tail1->size=max-loca;
tail1->start=loca;
}
int first_fit(int sizes,int id){//循环首次适应算法,在此之前已经检查尾部能不能插,将指针移到空闲链表队首进行遍历
// 找到合适的就分配,不能的话进行紧凑,紧凑完后继续分配
//需要输入的是所需分区的大小
NODE *p,*t;
int a=22;
for(p=head1;p->next!=NULL;p=p->next){
if(p->next->size>sizes){//p指向合适分区的前驱结点
//如果找到合适分区,进行分配
//分配其实就是对已分配链表的插入和对空闲链表的修改或删除
//对于已分配链表的操作
insert(sizes,p->next->start,id); //将分区插入到合适的位置
//对于空闲链表。其实直接修改就行,指针
p->next->start+=sizes;
p->next->size-=sizes;
return 0;
}
if(p->next->size==sizes) {
printf("TESTELSE\n");
insert(sizes,a,id); //将分区插入到合适的位置
//对空闲链表来说,如果等于就是对空闲链表的节点删除
printf("TEST===%d",p->next->next->start);
t=p->next->next;
p->next=t;
return 0;
}
// printf("p==NULL未执行%d\n",p->next);
if(p->next==NULL){
printf("p==NULL执行\n");
break;
}
}
if(p->next==NULL){
//找不到可以分配的空闲分区,进行紧凑技术
printf("找不到合适的空闲分区,进行紧凑:\n");
refresh();
//再比较紧凑后的分区,看是否能分配,然后输出结果
if(tail1->size<sizes)
printf("内存不足,请先释放内存!");
else{
printf("紧凑完毕,请重新输入!\n");
add();
}
}
}
void insert(int size,int loc,int id)//已分配链表的插入
{
//printf("TESTinsert\n");
NODE *p,*q;
q=(NODE *)malloc(sizeof(NODE));//
//printf("TESTinsert%d\n",t->next->start);
for(q=head;q->next->start<loc;)
q=q->next; //将q指向要插入节点的前驱节点
printf("TESTinsert\n");
pnew1=(NODE *)malloc(sizeof(NODE));
pnew1->size=size;
pnew1->start=loc;
pnew1->id=id;
p=q->next;
q->next=pnew1;
pnew1->next=p;
}
void create()//分配区的链表初始化
{
int id,size;
head=(NODE *)malloc(sizeof(NODE)); //创建头节点。
pnew=(NODE *)malloc(sizeof(NODE));
tail=(NODE *)malloc(sizeof(NODE));
head->next=NULL; //头节点指针域置NULL
tail=head; // 开始时尾指针指向头节点
printf("-------------------------\n");
printf("输入进程id:");
scanf("%d",&id);
printf("输入进程大小:");
scanf("%d",&size);
if(size<rest){
// printf("TESTcr\n");
rest-=size;
//pnew=NULL;
pnew->id=id; //新节点数据域存放输入的进程块号
pnew->size=size;
pnew->start=location;
location+=size;
pnew->next=NULL; //新节点指针域置NULL
tail=pnew; //为指针指向当前的尾节点
head->next=tail; //新节点插入到表尾
//tail=pnew; //为指针指向当前的尾节点
//接下来是对空闲链表的操作
tail1->size=max-size;
tail1->start=location;
}
else
printf("内存不足!\n");
}
void create1()//创建空闲分区指针
{
tail1=(NODE *)malloc(sizeof(NODE)); //创建尾节点。
head1=(NODE *)malloc(sizeof(NODE)); //创建头节点。
pnew1=(NODE *)malloc(sizeof(NODE));
head1->next=NULL; //头节点指针域置NULL
tail1=head1; // 开始时尾指针指向头节点
//pnew1=NULL;
pnew1->size=max;
pnew1->start=0;
pnew1->next=NULL; //新节点指针域置NULL
tail1=pnew1; //为指针指向当前的尾节点
head1->next=tail1; //新节点插入到表尾
// tail1=pnew1; //为指针指向当前的尾节点
}
void add()//已分配链表的尾添加
{
int id,size;
pnew=(NODE *)malloc(sizeof(NODE));
printf("输入进程id:");
scanf("%d",&id);
printf("输入进程大小:");
scanf("%d",&size);
if(rest>size){
rest-=size;
// printf("TEST add\n");
pnew->id=id; //新节点数据域存放输入的进程块号
pnew->size=size;
pnew->start=location;
location+=size;
pnew->next=NULL; //新节点指针域置NULL
tail->next=pnew; //新节点插入到表尾
tail=pnew; //为指针指向当前的尾节点
//接下来是对空闲链表的操作
tail1->size-=size;
tail1->start=location;
}
else{
// printf("TEST addfit\n");
first_fit(size,id);
}
}
void add1(int size,int loc)//空闲链表的插入
{
//第一次插入
//printf("TESTadd1\n");
pnew1=(NODE *)malloc(sizeof(NODE));
pnew1->size=size;
pnew1->start=loc;
head1->next=pnew1;
pnew1->next=tail1;
}
void add2(int size,int loc,NODE *t)//空闲链表的插入
{
//非第一次插入
printf("TESTadd2\n");
NODE *p;
pnew1=(NODE *)malloc(sizeof(NODE));
pnew1->size=size;
pnew1->start=loc;
p=t->next;
t->next=pnew1;
pnew1->next=p;
tail1=p;
}
void display()//输出
{
NODE *p;
printf("当前已分配情况:\n");
printf("--------------------------------------------\n");
printf("起始地址 进程id 分区大小\n");
for(p=head->next;p!=NULL;p=p->next){
// printf("起始地址 进程id 分区大小\n");
// printf("--------------------------------------------\n");
printf("%d %d %d\n",p->start,p->id,p->size);
}
printf("--------------------------------------------\n");
printf("当前空闲分区情况:\n");
printf("--------------------------------------------\n");
printf("起始地址 分区大小\n");
for(p=head1->next;p!=NULL;p=p->next){
// printf("起始地址 分区大小\n");
// printf("--------------------------------------------\n");
printf("%d %d\n",p->start,p->size);
}
}
void pdelete()
{
int id;
printf("请输入您要回收的进程id:");
scanf("%d",&id);
NODE *p,*q,*t;
for( p=head;p->next->id!=id;){
p=p->next; //将p指向要删除节点的前驱节点
if(p->next==NULL) //表明链表中的节点不存在
{
printf("输入的id有误!");
pdelete();
}
}
if(p->next->next==NULL){//假设删除的是尾分配区,直接调整空闲分区各值即可
tail1->start=p->next->start;
tail1->size+=p->next->size;
p->next=NULL;
tail1=p;
return;
}
// printf("TEST%d\n",head1->next->id);
// printf("TEST%d\n",tail1->id);
if(head1->next->id==tail1->id)
add1(p->next->size,p->next->start);
else{
for(t=head1;t->next->start<p->next->start;)
t=t->next; //将t指向要插入空闲链表的前驱节点
add2(p->next->size,p->next->start,t);
}
// printf("%d %d\n",p->next->size,p->next->start) ;
q=p->next; //q指向待删除的节点
p->next=q->next; //删除节点
free(q); //释放节点的内存单元
}
int main()
{
int n=1;
int i;
printf("--------------------------------------------\n");
printf("说明:本内存分配系统采用的是循环首次适应算法\n");
printf("--------------------------------------------\n");
//printf("请输入要进行的操作:\n");
while(1){
printf("1.创建进程 | 2.撤销进程 | 0.退出\n");
printf("请输入要进行的操作:");
// printf("1.创建进程 | 2.撤销进程 |0.退出\n");
scanf("%d",&i);
pnew=(NODE *)malloc(sizeof(NODE));
pnew1=(NODE *)malloc(sizeof(NODE));
switch(i){
case 1:
if(n==1){
create1();
create();
n++;
display();
}
else{
add();
display();
}
break;
case 2:
pdelete();
display();
break;
case 0:exit(0);
}
}
return 0;
}