当前位置:   article > 正文

Ubuntu22.2下C语言编程实现,首次,最佳适应算法_c语言首次适应算法高地址分配

c语言首次适应算法高地址分配

1.题目要求

编写C语言程序,模拟实现首次/最佳/最坏适应算法(选择其中之一即可)的内存块分配和回收,要求每次分配和回收后显示出空闲分区和已分配分区的情况。假设初始状态下,可用的内存空间为640KB。
假设下列作业请求序列:
(1)作业1 申请130 KB (2)作业2 申请60 KB (3)作业3 申请100 KB
(4)作业2 释放60 KB (5)作业3 释放100 KB (6)作业1 释放130 KB
显示每次作业申请或释放后当前内存情况。

2.分析设计

根据题目,分析设计如下:
(1)程序初始需要提供用户选择方式。选择首次适应算法,还是最佳是适应算法,选择作业的回收,作业的展示,程序的退出能。
(2)当用户选择首次适应算法或者最佳适应算法,需要用户输入分配内存的大小。在输入大小时在根据算法的设计进行分配。
(3)当内存分配过后,如果分配成功就需要提示成功,如果失败则需要提示失败。
(4)内存回收需要用户输入回收作业的ID,根据作业的ID对内存进行回收。在回收时要分多种情况进行判断。
(5)作业展示,需要向用户展示,作业的ID,起始地址,内存大小,状态是已分配还是空闲。
(6)一个作业需要用到数据结构中的双向列表,用一个双向列表来表示节点。

3.程序代码

#include <stdio.h>
#include <stdlib.h>

struct area
{
  int id;             // 编号
  int addr_front;     //首地址
  int addr_end;      //结束地址
  int size;           //分区大小
  int flag;           //分配标志,0表示空闲,1表示占用
  struct area *front; //上一分区
  struct area *next;  //下一分区
};

typedef struct area partion;

partion *head = NULL; //分区队列头节点
int need;             //需求
int choice = 1;       //操作选项

partion *createPartion(int id, int addr_front, int size, int flag); //生成一个节点
void inputNeed();                                                   //输入需求量
void assign(partion *ptr, int need);                                //分配分区
void first_fit();                                                   //首次适应算法
void best_fit();                                                    //最佳适应算法
void showMemoryInfo();                                              //打印分区分配状况
void recovery();                                                    //分区回收
void changeIdValue(partion *ptr, int delta);                        //改变从ptr开始所有节点的id值

int main(void)
{
  head = createPartion(0, 0, 640, 0);
  while (choice != 0)
  {
    puts("-------------------\n请选择操作:\n1:首次适应;\n2:最佳适应;\n3:内存回收;\n4:展示详细信息;\n0:推出......\n-------------------");
    scanf("%d", &choice);
    switch (choice)
    {
    case 1:
      inputNeed();
      first_fit();
      break;
    case 2:
      inputNeed();
      best_fit();
      break;
    case 3:
      recovery();
      showMemoryInfo();
      break;
    case 4:
      showMemoryInfo();
      break;
    case 0:
      puts("byebye");
      break;
    default:
      break;
    }
  }

  return 0;
}

//创建一个节点
partion *createPartion(int id, int addr_front, int size, int flag)
{
  partion *p = (partion *)malloc(sizeof(partion));
  p->id = id;
  p->addr_front = addr_front;
  p->addr_end=addr_front+size-1;
  p->size = size;
  p->flag = flag;
  p->front = NULL;
  p->next = NULL;
  return p;
}

void inputNeed()
{
  printf("请输入需要的内存大小:");
  scanf("%d", &need);
}

void first_fit()
{
  partion *fit = NULL;
  partion *ptr = head;
  while (ptr != NULL)
  {
    if (ptr->size >= need && ptr->flag == 0)//如果是空闲并且大小大于则给予分配
    {
      fit = ptr;
      break;
    }
    ptr = ptr->next;
  }
  if (fit != NULL)
  {
    assign(fit, need);
    printf("内存分配成功,分配如下:\n");
    showMemoryInfo();
  }
  else
  {
    puts("抱歉,内存分配失败!");
    free(fit);
  }
}

void best_fit()
{
  partion *fit = NULL;
  partion *ptr = head;
  int flag = 0; //flag 表示是否找到可分配的分区
  while (ptr != NULL)
  {
    if (ptr->flag == 0 && ptr->size >= need)
    {
      if (flag == 0)
      {
        //只有遇到的第一个可分配分区会执行此操作
        fit = ptr;
        flag = 1;
      }
      else
      {
        //若遇到可分配且分区更小即更适合的则更新
        if (ptr->size < fit->size)
        {
          fit = ptr;
        }
      }
    }
    ptr = ptr->next;
  }
  //先处理没找到合适分区的情况
  if (flag == 0)
  {
    puts("抱歉,未找到合适的分区!");
    free(fit);
    return;
  }
  //找到则分配
  assign(fit, need);
  puts("内存分配成功,分配如下:\n!");
  showMemoryInfo();
}

void showMemoryInfo()
{
  partion *ptr = head;
  puts("\n\n---------------------------------------------");
  puts("总内存分配情况如下:");
  puts("---------------------------------------------");
  puts("序号ID****开始地址****结束地址****内存大小****状态****");
  while (ptr != NULL)
  {
    printf("%-12d%-12d%-12d%-12d",ptr->id,ptr->addr_front,ptr->addr_end,ptr->size);
   // printf("序号id:%21d%10c\n开始地址:%10d%10c\n", ptr->id, '|', ptr->addr_front, '|');
    //printf("结束地址:%10d%10c\n", ptr->addr_end, '|');
    //printf("内存大小:%11d%10c\n", ptr->size, '|');
    printf("%-12s\n", ptr->flag == 0 ? "空闲" : "已分配");
    puts("-----------------------------------------------------");
    ptr = ptr->next;
  }
  puts("---------------------------------------------\n\n");
}

void assign(partion *ptr, int need)
{

  if (need == ptr->size)//空闲的空间恰好等同需要的空间
  {
    ptr->flag = 1;
    return;
  }
  //空闲的空间大于需要的空间
  partion *assigned = createPartion(ptr->id, ptr->addr_front, need, 1);
  assigned->next = ptr;
  assigned->front = ptr->front;
  changeIdValue(ptr, 1);//把后面的节点的id值都增加1
  ptr->addr_front += need;
  ptr->size -= need;
  if (ptr->front != NULL)//空闲区的头不空,就在前一个节点后面添加分配的节点
  {
    ptr->front->next = assigned;
  }
  else//空闲节点前没有节点
  {
    head = assigned;
  }

  ptr->front = assigned;//空闲节点的头指向新分配的
}

void recovery()
{
  printf("请输入需要回收作业的ID号:");
  int id, flag = 0;
  scanf("%d", &id);
  partion *ptr = head;
  while (ptr != NULL)
  {
    if (id == ptr->id)
    {
      flag = 1;
      break;
    }
    ptr = ptr->next;
  }
  if (flag == 0)
  {
    puts("没有找到你需要回收的作业!");
    return;
  }
  if (ptr->flag == 0)
  {
    puts("该ID已经是空闲的了");
    return;
  }
  if (ptr->front == NULL)
  {
    //第一个分区

    if (ptr->next == NULL || ptr->next->flag == 1)
    {
      //后面不空或后面没有
      ptr->flag = 0;
      return;
    }
    if (ptr->next->flag == 0)
    {
      //后面空
      ptr->size += ptr->next->size;
      ptr->flag = 0;//标记为空闲
      if (ptr->next->next != NULL)//把下一个节点的头指向该节点
      {
        ptr->next->next->front = ptr;
      }
      ptr->next = ptr->next->next;//合并两个节点

      free(ptr->next);//真实释放节点
      return;
    }
  }
  if (ptr->next == NULL)
  {
    //最后一个分区
    if (ptr->front == NULL || ptr->front->flag == 1)
    {
      //前面不空或者前没有
      ptr->flag = 0;
      return;
    }
    if (ptr->front->flag == 0)
    {
      //前面为空
      ptr->front->size += ptr->size;
      ptr->front->next = NULL;
      free(ptr);
      return;
    }
  }
  if (ptr->front->flag == 0 && ptr->next->flag == 0)
  {
    //上下都空
    ptr->front->size += ptr->size + ptr->next->size;
    ptr->front->next = ptr->next->next;
    if (ptr->next->next != NULL)
    {
      ptr->next->next->front = ptr->front;
    }
    changeIdValue(ptr->front->next, -2); //更改id
    free(ptr->next);
    free(ptr);
    return;
  }
  if (ptr->front->flag == 0 && ptr->next->flag == 1)
  {
    //上空下不空
    ptr->front->size += ptr->size;
    ptr->front->next = ptr->next;
    ptr->next->front = ptr->front;
    changeIdValue(ptr->front->next, -1);
    free(ptr);
    return;
  }
  if (ptr->front->flag == 1 && ptr->next->flag == 0)
  {
    //上不空下空
    ptr->size += ptr->next->size;
    if (ptr->next->next != NULL)
    {
      ptr->next->next->front = ptr;
    }
    partion *p_next = ptr->next;  //保存一下下方为空的那个分区,以便一会释放 
    ptr->next = ptr->next->next;
    ptr->flag = 0;
    changeIdValue(ptr->next, -1);
    free(p_next);
    return;
  }
  if (ptr->front->flag == 1 && ptr->next->flag == 1)
  {
    //上下都不空
    ptr->flag = 0;
    return;
  }  
}

void changeIdValue(partion *ptr, int delta)
{
  while (ptr != NULL)
  {
    ptr->id += delta;
    ptr = ptr->next;
  }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320

4.运行截图

首次适应算法
开始
在这里插入图片描述
(1)作业1 申请130 KB
在这里插入图片描述

(2)作业2 申请60 KB
在这里插入图片描述

(3)作业3 申请100 KB
在这里插入图片描述

(4)作业2 释放60 KB
在这里插入图片描述

(5)作业3 释放100 KB
在这里插入图片描述

(6)作业1 释放130 KB

在这里插入图片描述

最佳适应算法
开始:
在这里插入图片描述

(1)作业1 申请130 KB
在这里插入图片描述

(2)作业2 申请60 KB
在这里插入图片描述

(3)作业3 申请100 KB
在这里插入图片描述

(4)作业2 释放60 KB
在这里插入图片描述

(5)作业3 释放100 KB
在这里插入图片描述

(6)作业1 释放130 KB
在这里插入图片描述

5.程序说明

总流程图:
在这里插入图片描述

总流程图是提供程序开始运行的界面图,供用户选择,其中用户可以选择的选项有,首次适应算法,最佳适应算法,内存回收,内存作业的显示。每选择一个功能就执行相应的函数代码。

首次适应算法流程图:
在这里插入图片描述

首次适应算法,首先用户输入作业需要的内存大小,然后程序从低地址向高地址寻找空间空间,如果找到空闲空间,如果空闲空间的大小比作业需要的空间大则进行分配,如果空闲空间比作业需要的空间小,则继续寻找下一个空闲空间。如果所有的空闲空间都寻找完也没有符合要求的,那么作业的内存分配失败。

最佳适应算法流程图
在这里插入图片描述

最佳适应算法,首页用户输入作业需要的内存空间,程序从低地址开始寻找空闲空间,如果第一次找合适的空间分配,就临时存储这个空间地址,继续向下继续寻找符合的地址空间,如果寻找到合适的空间空间范围,且新的空间大小比临时存储的空间大小还小,则新的符合空间更新为临时符合空间,依次类推到最后。如果程序没有临时最佳的地址空间,则并没有分配到内存,所以作业内存分配失败。如果有临时最佳空间地址,则把最佳的地址空间分配给作业。

内存回收流程图:
在这里插入图片描述

作业回收,首先需要需要输入回收作业的ID,先判断作业ID是否存在,存在才能进行释放,在ID存在的前提下判断,该ID的作业状态,只有为已分配状态猜才进行释放。释放则的分情况讨论。释放的节点分为头部,中间,尾部。如果释放的节点前后已经有空闲空间,就需要进行合并。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/755525
推荐阅读
相关标签
  

闽ICP备14008679号