/*
Title: 首次适应算法
Author: Brian
Date: 2010/05/31
*/
#include <iostream>
#include <cstdlib> // system()
using namespace std;
typedef struct SNode { // Space Node
    int start,end; // 起始,结束
    int length; // 长度大小
    struct SNode *next; // 指向下一结点的指针
}* SP;
SP space=(SP)malloc(sizeof(SNode)); // 全局变量,内存空间头结点
void DispSpace() { // 显示内存空间分配情况
    SP p=space;
    cout<<"\n  空闲区说明表 \n"
        <<"---地址--长度---\n";
    while (p->next)
    {
        cout<<"    "<<p->next->start
            <<"    "<<p->next->length<<endl;
        p=p->next;
    }
    cout<<"----------------\n";
}
void Initial() { // 初始化说明表
    SP p,q;
    p=(SP)malloc(sizeof(SNode));
    q=(SP)malloc(sizeof(SNode));    
    p->start=14; p->length=12; p->end=26;
    q->start=32; q->length=96; q->end=128; // 指导书上的作业分配
    space->next=p; // 与头结点连接
    p->next=q;
    q->next=NULL;
    DispSpace();
}
void Allocation(int len) { // 分配内存给新作业
    SP p=space,q;
    while (p->next) {
        if (p->next->length < len)
            p=p->next;
        else if (p->next->length > len) {
            p->next->start=p->next->start+len;
            p->next->length=p->next->length-len;
            cout<<"分配成功!\n";
            DispSpace(); return;
        }
        else {
            q=p->next;
            p->next=q->next;
            cout<<"分配成功!\n";
            DispSpace(); return;
        }    
    } 
    cout<<"分配失败!\n";
    DispSpace(); return;
}
void CallBack(int sta,int len) { // 回收内存
    SP p=space,q=p->next,r; // 开始地址和长度
    p->end=0;
    int en=sta+len;
    while (q) {
        if (sta == 0) { // 初始地址为0
            if (en == q->start) { // 正好回收
                q->start=0;
                q->length=q->end;
                return;
            }
            else {
                r=(SP)malloc(sizeof(SNode));
                r->start=sta; r->length=len; r->end=en;
                p->next=r;
                r->next=q;
                return;
            }
        }
        else if ((p->end < sta) && (q->start > en)) { // 上邻区
            r=(SP)malloc(sizeof(SNode));
            r->start=sta; r->length=len; r->end=en;
            p->next=r;
            r->next=q;
            return;
        }
        else if ((p->end < sta) && (q->start == en)) { // 邻区相接
            q->start=sta;
            q->length=q->end-sta;
            return;
        }
        else if ((p->end == sta) && (q->start < en)) { // 下邻区
            p->end=en;
            p->length=en-p->start;
            return;
        }
        else if (p->end==sta && q->start==en) { // 邻区相接
            p->end=q->end;
            p->length=p->end-p->start;
            p->next=q->next;
            return;
        }
        else {
            p=p->next;
            q=q->next;
        }
    }
}
void main() {
    Initial();
    cout<<"现在分配大小为 6K 的作业 4 申请装入主存: ";
    Allocation(6); // 分配时参数只有长度    
    //--------指导书测试数据演示----------
    cout<<"现回收作业 3 (起址10,长度4)\n";
    CallBack(10,4);
    DispSpace();
    cout<<"现回收作业 2 (起址26,长度6)\n";
    CallBack(26,6);
    DispSpace();
    //---------------演示结束-------------
    system("pause");
}
 
/*
Title: 位示图法
Author: Brian
Date: 2010/05/25
*/
#include <iostream>
#include <cstdlib>
using namespace std;
typedef struct PNode { // 进程PCB    
    struct PNode *next; // 后向指针
    char name[12]; // 进程名
    int *PT; // 页表
    int size; // 进程所需要的空间
}* Proc;
Proc H=(Proc)malloc(sizeof(PNode)); // 进程头结点
Proc CurrJob; // 当前进程指针
int BG_DEF[8][8] = {  // 指导书上的初始条件
    {1,1,0,0,1,1,1,0},
    {0,1,0,1,0,1,0,0},
    {0,0,0,0,0,0,0,0},
    {1,0,0,0,0,0,0,1},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0} 
};
int FREE_DEF = 54; // 指导书上初始条件的空闲块数
int BG[8][8]={0}; // 用户自定义位示图
int FREE=64; // 用户自定义空闲块数
void DispBG(int flag) // 显示当前位示图 F
{
    cout<<"\n字节号\\位数\t0\t1\t2\t3\t4\t5\t6\t7\n";
    for(int i=0; i<8; i++)
    {
        cout<<'\t'<<i;
        for(int j=0; j<8; j++)
        {
            if (flag==1)
                cout<<"\t"<<BG[i][j];
            else cout<<"\t"<<BG_DEF[i][j];
        }
        cout<<endl;
    }
    cout<<endl;
}
void Initial() // 用户选取坐标初始化内存块
{
    DispBG(1);
    cout<<"\n请输入您想要分配的块号坐标,以 -1 -1 结束:\n";
    int i,j;
    while (1)
    {
        cin>>i>>j;
        if (i+j==-2) // i==-1 && j==-1
            break;
        BG[i][j]=1;
        FREE--;
    }
    DispBG(1);
}
void Allocation(int flag) //内存分配
{
    int i,j,k,kflag=1; // 进程个数
    Proc s=H;
    s=s->next=(Proc)malloc(sizeof(PNode));
    cout<<"请输入进程名和内存大小: ";
    cin>>s->name>>s->size;
    if (flag==1)
    {
        if (s->size > FREE)
        {
            cout<<"空间不足,分配失败!";
            return;
        }
        FREE-=s->size;
    }
    else {
        if (s->size > FREE_DEF) {
            cout<<"空间不足,分配失败!";
            return;
        }
        FREE_DEF-=s->size;
    }
    
    s->PT=new int[s->size]; // 新建PT表
    k=0;
    if (flag==1) // 用户自定义位示图
    {
        for (i=0; i<8 && kflag; i++)
            for (j=0; j<8 && kflag; j++)
            {
                if (!BG[i][j])
                {
                    BG[i][j]=1;
                    FREE--;
                    s->PT[k++]=8*i+j;
                    if (k==s->size)
                    {
                        cout<<"分配完成!\n";
                        kflag=0;
                    }
                }
            }
    }
    else // 实验指导书位示图
    {
        for (i=0; i<8 && kflag; i++)
            for (j=0; j<8 && kflag; j++)
            {
                if (!BG_DEF[i][j])
                {
                    BG_DEF[i][j]=1;
                    FREE_DEF--;
                    s->PT[k++]=8*i+j;
                    if (k==s->size)
                    {
                        cout<<"分配完成!\n";
                        kflag=0;
                    }
                }
            }
    }
    s->next=NULL;
}
void CallBack(int flag) //内存回收
{
    char name[12];
    cout<<"请输入需要回收的进程名: ";
    cin>>name;
    Proc p=H->next,q=H;
    while (p)
    {
        if (strcmp(name,p->name)==0) // 删除进程,回收内存
        {
            for(int i=0; i<p->size; i++) // 修改该进程位示图
            {
                int m=p->PT[i]/8;
                int n=p->PT[i]%8;
                if (flag==1)
                {
                    BG[m][n]=0;
                    FREE++;
                }
                else {
                    BG_DEF[m][n]=0;
                    FREE_DEF++;
                }
            }
            
            q->next=p->next; // 删除进程结点
            free(q);
            cout<<"回收成功!\n";
            return;
        }
        p=p->next;
        q=q->next;
    }
    cout<<"无此进程,回收内存失败!\n";
}
void DispPT()
{
    char name[12];
    cout<<"请输入要打印页表的进程名: ";
    cin>>name;
    Proc p=H->next;
    while (p)
    {
        if (strcmp(name,p->name) == 0)
        {
            cout<<"  块号\n"
                <<"--------\n";
            for (int i=0; i<p->size; i++)
                cout<<"    "<<p->PT[i]<<endl;
            cout<<"--------\n";
            return;
        }
        p=p->next;
    }
    cout<<"该进程不存在!\n";
}
void Welcome()
{
    cout<<"----------位示图法---------\n"
        <<"       1. 新进程内存分配\n"
        <<"       2. 旧进程内存回收\n"
        <<"       3. 打印进程页表\n"
        <<"       4. 打印位示图\n"
        <<"       5. 退出系统\n"
        <<"-----------------------------------\n";
}
void main()
{
    H->next=NULL;
    int flag;
    cout<<"内存初始化方式: 1.自定义 2.指导书\n"
        <<"请选择: ";
    cin>>flag;
    if (flag==1) Initial(); // 用户选取坐标初始化内存块
    int choice;
    while (1)
    {
        Welcome();
        cin>>choice;
        switch (choice)
        {
        case 1: Allocation(flag); break; // 进行一次分配内存工作
        case 2: CallBack(flag); break; // 回收用户指定进程的内存
        case 3: DispPT(); break; // 打印用户指定进程的页表
        case 4: DispBG(flag); break; // 打印用户指定位示图
        case 5: cout<<"\n退出成功!\n"; system("pause"); exit(1);
        }
    }
}