爲了實現動態分區分配,一般將系統中的空閒分區連接成一個鏈。所謂順序查找是指依次搜索空閒分區鏈上的空閒分區,去尋找一個大小能知足要求的分區。 --------計算機操做系統(第四版)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"); }