为了实现动态分区分配,一般将系统中的空闲分区连接成一个链。所谓顺序查找是指依次搜索空闲分区链上的空闲分区,去寻找一个大小能知足要求的分区。 --------计算机操做系统(第四版)node
要求,空闲分区链以地址递增的顺序连接。每次从链首开始,直到找到第一个能知足要求的空闲分区为止。
简单来讲,就是,每次都从第一个开始顺序查找,找到一块区域能够知足要求的。算法
与FF算法区别就是,不是每次都从首次开始,而是从上次找到的空闲分区的下一个空闲分区开始。(第一次查找的话也是从首页开始)。学习
将全部空闲分区按照空闲分区容量大小从小到大的顺序链接起来,造成一个空闲分区链。
即,每次都是找空间容量不但能够知足要求的空闲区,并且该空闲分区的容量还要最接近要求的容量大小。编码
与BF算法相反,WF算法是按照空闲分区容量从大到小的顺序链接起来的,并且每次找空闲分区的时候也是按照空闲分区容量最大的。操作系统
#include<stdio.h> #include<stdlib.h> typedef struct lei_item //表示空闲分区表中的表箱 { int id; //假如 id 为-1,表示此分区时一个空闲分区。 int base; //指向分区的首地址 int size; //表示分区大小 int status; //表示此分区是否已经分配 0表示空闲 1表示已经分配 }Item; typedef Item datatype; typedef struct lei_list { datatype* node; //表示一个datatype类型的链表的结点 struct lei_list* front; struct lei_list* next; }List; #define Max 640 int memory = Max; //定义可用内存空间为640 List init(){ //初始化一个链表; List list; list.node = (datatype *)malloc(sizeof(datatype)); list.node->base = 0; list.node->id = -1; //-1表示是空闲分区 list.node->size = memory; list.node->status = 0; list.front = list.next = NULL; return list; } datatype* input(){ //初始化打算申请的内存分区节点 datatype* item = (datatype *)malloc(sizeof(datatype)); printf("请输入做业号:"); scanf("%d",&item->id); printf("请输入所须要的内存的大小:"); scanf("%d",&item->size); item->status = 0; return item; } int First_fit(List *list){ datatype* item = input(); List* temp = list; //定义一个临时变量list* ,指向list while (temp) { if(temp->node->status == 0 && temp->node->size > item->size){ //若是此前的分区未分配,,而且分区大小大于 请求分配的大小 那么此时就能够进行分配 List *front = temp->front; //存储当前未分配分区的 上一个分区地址 List *next = temp->next; //存储当前未分配分区的 下一个分区地址 int base = temp->node->base; //记录未分配当前分区的首地址 datatype* new_node = (datatype*)malloc(sizeof(datatype)); // 多余出来的部分要新创建一个分区 new_node->id = -1; //而后须要对这个新的分区进行一些信息的设置 new_node->size = temp->node->size - item->size; //新分区的大小 等于 还未分配的时的分区大小 - 请求分配的结点的大小 temp->node = item; //对请求分配的分区结点进行分配 temp->node->status = 1; new_node->status = 0; new_node->base = base + temp->node->size; //新创建分区的首地址是 请求分配的分区的首地址 + 请求分配的分区的大小 List* temp_next = (List*)malloc(sizeof(List)); //临时节点 (申请一个新的链表节点 表示下一个分区) 而且进行初始化 temp_next->node = new_node; //保存下一个的分区的信息 temp_next->front = temp_next->next = NULL; if(front == NULL && next == NULL){ //若是 front和next节点都是空,代表它是第一次分配分区 temp->node->base = 0; //初始化首地址 temp->next = temp_next; temp_next->front = temp; } if(front == NULL && next != NULL){ //在第一个分区中插入新的分区 temp->node->base = 0; temp->node->status = 1; temp_next->next = temp->next; temp->next = temp_next; } if(front != NULL){ //代表不是第一次分配节点,此时须要在中间插入下一个节点 temp->node->base = temp->front->node->base+temp->front->node->size; //初始化首地址 temp_next->next = temp->next; //保证新插入的节点会记录原先节点的下一个节点的首地址 temp_next->front = temp; // 首尾都须要保证 temp->next = temp_next; //最后让所申请的分区节点的下一个节点指向 咱们刚刚创建的临时节点 } return 1; } else if(temp->node->status == 0 && temp->node->size == item->size) { item->base = temp->front->node->base+temp->front->node->size; //新插入分区的首地址 等于上一个分区的 首地址+分区的大小 item->status = 1; //表示已经分配 temp->node = item; return 1; } else{ temp = temp->next; continue; } temp = temp->next; } return 0; } int Momory_recycle(List *list){ List* temp = list; //申请一个链表节点 指向list 的头节点 int number; //用于存放要释放的节点的分区号 printf("请输入须要回收的ID号:"); scanf("%d",&number); while (temp) { if(temp->node->id == number) //首先找到 节点id = number 的节点,而后分四种状况讨论 { // 1、 要回收的是第一个结点 if(temp->front == NULL){ temp->node->status = 0; temp->node->id = -1; if(temp->next == NULL){ temp->node->size = temp->node->size + temp->next->node->size; temp->next = temp->next; return 1; } return 1; } //2、 先后都没有空闲的分区 //最简单, 直接改变 分区的 id 和 分区的状态就能够了。 // 若是回收第一个分区的话 必需要先进行处理,若是不先进行处理 ,判断 temp->front->node->id != -1 会报一个段错误。由于temp-》front 此时指向的是null if(temp->front->node->id != -1 && temp->front->node->status != 0 && temp->next->node->id != -1 && temp->next->node->status != 0){ temp->node->status = 0; temp->node->id = -1; return 1; } //3、要回收的节点 前面和后面都是空闲的 // 将三个空闲区合并到一块儿,起始地址为前面的分区的起始地址, 大小为三个空闲区大小之和 //还须要作一个判断,若是 if(temp->front->node->id == -1 && temp->front->node->status == 0 && temp->next->node->id == -1 && temp->next->node->status == 0){ List* front = temp->front; List* next = temp->next; front->node->size = front->node->size + temp->node->size + next->node->size; front->next = next->next; if(next->next == NULL){ free(temp); return 1; } //若是不是最后一个结点的话就会多一个步骤 // 让 next->next->front 指向上一个结点 else { next->next->front = front; free(temp); return 1; } return 1; } // 4、 要回收的节点 前面的节点是空闲的 //合并后的分区起始地址为前一个结点, 分区大小为前一个节点 与 当前节点之和。 if(temp->front->node->id == -1 && temp->front->node->status == 0){ List* front = temp->front; front->next = temp->next; temp->next->front = front; front->node->size += temp->node->size; free(temp); return 1; } //5、 要回收的节点 后面的额节点是空闲的 //合并后的分区首地址为当前节点 , 分区大小为当前节点 与 当前节点的下一个结点大小之和。 // 这个须要多一个步骤, 改变分区的 id 和 分区的状态。 // 还要注意一点: 当要回收的空间是和 系统最后的空闲区相邻时 , temp->next->next 指向的是null; if(temp->next->node->id == -1 && temp->next->node->status == 0){ List* next = temp->next; // 此时来判断 temp->next 是不是系统的最后一个结点 // 此时只将当前节点 和下一个结点合并就能够了 //即 首地址不变, 分区状态 和 分区id进行变化 temp->node->size = temp->node->size + next->node->size; temp->node->status = 0; temp->node->id = -1; temp->next = next->next; if(next->next == NULL){ free(next); return 1; } //若是不是最后一个结点的话就会多一个步骤 // 让 next->next->front 指向上一个结点 else { next->next->front = temp; free(next); return 1; } } } temp = temp->next; } return 0; } void Momery_state(List *list){ List* temp = list; printf("-----------------------------------\n"); printf("内存分配情况\n"); printf("-----------------------------------\n"); while (temp) { if(temp->node->status == 0 && temp->node->id == -1){ printf("分区号:FREE\n"); printf("起始地址:%d\n",temp->node->base); printf("内存大小:%d\n",temp->node->size); printf("分区状态:空闲\n"); } else { printf("分区号:%d\t起始地址:%d\n",temp->node->id,temp->node->base); printf("内存大小:%d\n",temp->node->size); printf("分区状态:已分配\n"); } printf("-----------------------------------\n"); temp = temp->next; } } int Best_fit(List *list){ int min = 0; //记录 最小分区的结点的大小 int base_min = 0; //记录 最小节点的结点的起始地址 List* temp = list; datatype* item = input(); // 要对 item 的 起始地址 和 分配状态进行初始化 while (temp) { //若是分区未分配 就要进行 比较操做, 而且记录差值 和 分区的id号 if(temp->node->status == 0 && temp->node->id == -1&& temp->node->size > item->size){ if(min == 0){ //加入min为0 表示还未找到一个能够分配的分区 min = temp->node->size; base_min = temp->node->base; } else { if(temp->node->size < min){ // 找到一个以后,须要找出最小的分区 也就是它的 size最小。 min = temp->node->size; base_min = temp->node->base; } } } if(temp->node->status == 0 && temp->node->id == -1 && temp->node->size == item->size){ int base = temp->node->base; temp->node = item; temp->node->status = 1; temp->node->base = base; return 1; } temp = temp->next; } //由于可能没有任何一个空间能够知足要求须要作一个判断处理 temp = list; while (temp) { if(temp->node->base == base_min){ datatype* temp_node = (datatype*)malloc(sizeof(datatype)); //会有多余的空间多出来 因此须要在创建一个结点插入到链表中 temp_node->id = -1; temp_node->status = 0; temp_node->base = base_min + item->size; temp_node->size = temp->node->size - item->size; temp->node = item; //对item进行完整的初始化 temp->node->base = base_min; temp->node->status = 1; List* temp_list_node = (List*)malloc(sizeof(List)); //新申请一个 链表的结点 而且初始化 temp_list_node->node = temp_node; temp_list_node->front = temp; temp_list_node->next = temp->next; temp->next = temp_list_node; return 1; } temp = temp->next; } } int main(){ printf("分区模拟\n"); List list = init(); int select; int insert_state,recycle_state; int insert_state_best; do { printf("请输入要进行的操做\n"); printf("1-首次适应算法, 2-最佳适应算法, 3-内存回收, 4-显示内存情况, 5-退出\n"); scanf("%d",&select); switch (select) { case 1: // 1. 首次适应算法 insert_state = First_fit(&list); if(insert_state == 0){ printf("分配失败\n"); } else { printf("分配成功!\n"); } break; case 2: // 2. 最佳适应算法 insert_state_best = Best_fit(&list); if(insert_state_best == 1){ printf("分配成功\n"); } else { printf("分配失败\n"); } break; case 3: //3.内存回收 recycle_state = Momory_recycle(&list); if(recycle_state == 1){ printf("回收成功!\n"); } else{ printf("回收失败\n"); } break; case 4: //4.显示内存情况 Momery_state(&list); break; } } while (select != 5); system("pause"); }