操作系统之动态分区代码实现

动态分区 C++代码 这里用的是链表可能有些复杂了 其他简单的数据结构也可实现。

#include<stdio.h>
#include<stdlib.h>
//typedef int elemtype;
typedef struct 
{
	char name;			//作业名称
	int size;			//分区大小
	int beginaddress;	//分区开始地址
	int flag;			//分区的使用状态
}elemtype;
typedef struct LinkedQueueNode	//节点
{
	elemtype data;
	struct LinkedQueueNode *next;
}LinkedQueueNode;
typedef struct LQueue	//队列
{
	struct LinkedQueueNode *front;//头
	struct LinkedQueueNode *rear;//尾
}LQueue,* LinkedQueue;

LinkedQueue Init_LinkedQueue()	//队列的初始化
{
	LinkedQueue Q=(LinkedQueue)malloc(sizeof(LQueue));
	LinkedQueueNode *head=(LinkedQueueNode *)malloc(sizeof(LinkedQueueNode));
	head->next=NULL;
	Q->front=head;
	Q->rear=head;
	return Q;
}
int Init_LinkedQueue_Empty(LinkedQueue Q)		//判队列空
{
	if(Q->front==Q->rear)
		return 1;
	else
		return 0;
}
int Enter_LinkedQueue(LinkedQueue Q,elemtype x)	//入队 队尾入队
{
	LinkedQueueNode *node;
	node=(LinkedQueueNode *)malloc(sizeof(LinkedQueueNode));
	if(node==NULL)
	{
		printf("申请节点信息错误。\n");
		return 0;
	}
	node->data=x;
	node->next=NULL;
	Q->rear->next=node;
	Q->rear=node;//队尾元素更替 
	return 1;
}
int Delete_LinkedQueue(LinkedQueue Q)	//出队
{
	LinkedQueueNode *node;
	elemtype x;
	if(Q->front==Q->rear)
	{
		printf("队列为空,无法出队。\n");
		return 0;
	}
	else
	{
		node=Q->front->next;
		x=node->data;
		
		Q->front->next=node->next;
		if(node==Q->rear)
			Q->rear=Q->front;
		free(node);
		return 1;
	}
}
int GetFront_LinkedQueue(LinkedQueue Q)//取队头元素
{
	//LinkedQueueNode *node;
	int x;
	if(Q->front==Q->rear)
	{
		printf("队列为空,无法出队。\n");
		return 0;
	}
	else
	{
		x=Q->front->next->data.size;
		return x;
	}
}
int SIZE=2;
void menu();//输出菜单显示
void printQueue(LinkedQueue Q);//按顺序输出队列内容操作
void Distribute(LinkedQueue Q);
void Recycle(LinkedQueue Q);

int main()
{
	LinkedQueue Q;
	int choose;
	elemtype temp;
	
	Q=Init_LinkedQueue();//队列初始化	
	
	temp.size=1024;
	temp.beginaddress=0;
	temp.flag=0;
	Enter_LinkedQueue(Q,temp);

	menu();	
	for(;;)
	{
		printf("\n\n请输入选项:\t");
		scanf("%d",&choose);
		if(choose==0)
		{
			//printf("t0.退出\n");
			break;
		}
		switch(choose)
		{
		case 1:
			{
				printf("分配内存操作\n");
				Distribute(Q);
				break;
			}
		case 2:
			{	
				printf("回收内存操作\n");
				Recycle(Q);
				break;
			}
		case 3:
			{
				printf("显示内存使用情况\n");
				printQueue(Q);
				break;
			}
			default :break; 
		}
	}
}
void menu()
{
	printf("\n\t\t1.分配内存\n");
	printf("\t\t2.回收内存\n");
	printf("\t\t3.显示内存使用情况\n");
	printf("\t\t0.退出\n");
}
void printQueue(LinkedQueue Q)
{
	int icount=0;
	LinkedQueueNode *node;
	node=(LinkedQueueNode *)malloc(sizeof(LinkedQueueNode));
	if(node==NULL)
	{
		printf("申请节点信息错误。\n");
		return ;
	}
	node=Q->front->next;

	printf("分区号\t作业名\t起始地址(K)\t分区大小(KB)\t状态\n");
	//队列肯定不为空
	for(; 1 ;)//队列空时输出结束			! Init_LinkedQueue_Empty(T)
	{	
		
		
		printf("%-8d",icount++);						//输出分区号
		if(node->data.flag != 0)
		{
			printf("%-8c",node->data.name);				//输出分区名称
		}
		else
			printf("\t");

		printf("%-8d\t",node->data.beginaddress);	//输出分区起始地址
		printf("%-8d\t",node->data.size);			//输出分区大小
		printf("%-8d\n",node->data.flag);			//输出分区现在的使用状态
		
		if(node->next==Q->rear->next)	break;//程序出口	
		node=node->next;
	}
}
void Distribute(LinkedQueue Q)
{
	int usize;			//分区大小
	int ubeginaddress;	//分区开始地址

	int icount=0,min=1025,i;
	elemtype temp;
	
	LinkedQueueNode *node;
    LinkedQueueNode *node1;
 	LinkedQueueNode *node2;

	node=(LinkedQueueNode *)malloc(sizeof(LinkedQueueNode));
	node1=(LinkedQueueNode *)malloc(sizeof(LinkedQueueNode));
  	node2=(LinkedQueueNode *)malloc(sizeof(LinkedQueueNode));
	node=Q->front->next;//此时node 节点为头节点
	
	printf("请输入作业名(一个字符):");
	getchar();// 接受回车
	scanf("%c",&temp.name);
	printf("请输入作业所占内存的大小:");
	scanf("%d",&temp.size);
	for(i=1; 1 ;i++)//肯定可以找到
	//查找判断作业大小是否能放下  如果能放下则找出最接近该任务大小的分区
	{
		
		//找到一个节点 能放下所要求的大小 并且最接近该大小
		if( (node->data.flag==0) && (temp.size<=node->data.size) && (node->data.size-temp.size)<min)
		{	//该节点未存储内容      节点大小大于所要求的节点大小       最接近需求大小
			icount=i;//第几个分区
			min=node->data.size-temp.size;
		}
		if(node->next==Q->rear->next)	break;
		node=node->next;//移向下一个节点
	}
	if(min==1025)//说明此时内存中空闲部分无法满足所要求的大小
	{
		printf("插入操作失败。\n");
		
		return;
	}
	node=Q->front;//重新将node置回头节点
	for(i=1;1;i++)//找到满足要求的节点的前一个位置
	{
		if(i>=icount)//count 已分配分区号
			break;
		node=node->next;
	}
	if(min<=SIZE)
	//如果差值小于size 不进行分割 直接将该内存整块分配给该任务//起始位置不变 大小不变
	{
		node->next->data.flag=1;
		node->next->data.name=temp.name;
	}
	else
	{
		usize=node->next->data.size;//暂时记录相关数据
		ubeginaddress=node->next->data.beginaddress;
		//node1
		node1->data.name=temp.name;
		node1->data.size=temp.size;
		node1->data.beginaddress=ubeginaddress;
		node1->data.flag=1;
		//node2  没有name
		node2->data.size=usize-temp.size;
		node2->data.beginaddress=ubeginaddress+temp.size;
		node2->data.flag=0;
		//删除一个节点插入两个节点		
		node1->next=node2;
		node2->next=node->next->next;
		node->next=node1;
	}
	return;
}

void Recycle(LinkedQueue Q)
{
	char name;
	LinkedQueueNode *node;
	LinkedQueueNode *node1;
	node=(LinkedQueueNode *)malloc(sizeof(LinkedQueueNode));
	node1=(LinkedQueueNode *)malloc(sizeof(LinkedQueueNode));
	node=Q->front;//此时node 节点为头节点

	printf("请输入作业名(一个字符):");
	getchar();// 接受回车
	scanf("%c",&name);

	for(;;)
	{
		if(name==node->next->data.name)
			break;
		if(node->next->next==Q->rear->next)//到达链表的最后一个节点  查找失败
		{
			printf("队列中无此名称的节点,节点查找失败。\n");
			return;
		}
		node=node->next;
	}

	//先将自己的数据清空  
	node1->data.size=node->next->data.size;
	node1->data.beginaddress=node->next->data.beginaddress;
	node1->data.flag=0;
	node1->next=node->next->next;
	node->next=node1;
	if(node->next->next==Q->rear->next)
	{
		elemtype x;
		x.beginaddress=0;
		x.size=1024;
		x.flag=0;
		Enter_LinkedQueue(Q,x);
		printQueue(Q);
		return;
	}
	if(node->next!=Q->rear&&node->next->next->data.flag==0)//首先保证所要删除的后继节点存在  再判断所要删除的节点的后继节点未分配出去时
	{
		node->next->data.size+=node->next->next->data.size;
		node->next->next=node->next->next->next;
	}
	if(node->data.flag==0&&node!=Q->front)//所要删除的前一个空间也未分配时将两个空间合并并且不是队首 
	{
		node->data.size+=node->next->data.size;//空间大小的合并
		node->next=node->next->next;//删除所要删除的节点
	}
	return;	
}

如有错误,望大佬指出~

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值