/************************************************************************/ /* 功能: 模拟实现可变分区存储管理的最佳适应算法的链表类 时间:2014年9月1日21:57:21 作者:信管1201 1205020116 肖锋 */ /************************************************************************/ #include "Link.h" #include <iostream> using namespace std; //freeLink的定义实现 //void swap(int index1, int index2); //交换连个节点的信息 void freeLink::swap(int index1, int index2) { //交换这两个索引节点的所有信息 int i = 0; Node* p1 = head; while (i < index1) { p1 = p1->next; ++i; } int j = 0; Node* p2 = head; while (j < index2) { p2 = p2->next; ++j; } //p1和p2指向两个不同的节点,将要交换这两个节点,但是链表的位置不变 int size = p2->size; int adress = p2->adress; p2->size = p1->size; p2->adress = p1->adress; p1->size = size; p1->adress = adress; } //Node* getNode(int index); freeLink::Node* freeLink::getNode(int index) { int i = 0; Node* p=head; while (i < index) { p = p->next; ++i; } return p; } //给自由链表前后的合并分区,循环首次适应算法 //void pingJie2(); void freeLink::pingJie2() { //首先把链表按照地址的大小排序 //冒泡排序 int count = 0; Node* p = head; while (p != tail) { p = p->next; ++count; } //冒泡排序,吧链表按地址递增的方式存放 for (int i = 1; i <= count; ++i) { for (int j = 1; j <= count - i; ++j) { Node *p1, *p2; p1 = getNode(j); p2 = getNode(j + 1); if (p1->adress > p2->adress) { swap(j, j + 1); } } } //排序完成之后考虑是否要合并 //考虑4种情况 Node *p1, *p2, *p3; if (count == 1) return; //只有一个空闲的节点还合并个屁啊 else if (count == 2) {//如果只有两个空闲的节点的话,那么就直接考虑向后合并 p1 = head->next; p2 = p1->next; if ((p1->adress + p1->size) == p2->adress) {//如果成立就直接合并这两个节点 p1->size += p2->size; //吧容量合并到p1上 delete p2; p1->next = nullptr; tail = p1; } } else //这就一般的情况,那就要考虑四种情况了 { p1 = head->next; p2 = p1->next; p3 = p2->next; //指向前三个,以p2为操作对象,进行判断 //一直判断到链表尾部 while (p3 != nullptr) { if ((p1->adress + p1->size) == p2->adress || (p2->adress + p2->size) == p3->adress) //要么前向,要么后巷,或者全要 { if ((p1->adress + p1->size) == p2->adress && (p2->adress + p2->size) != p3->adress) {//前向 //吧p2去除掉合并到p1里面去 p1->size += p2->size; //去除p2,不用考虑为节点 p1->next = p3; delete p2; p2 = p3; p3 = p2->next; } else if ((p1->adress + p1->size) != p2->adress && (p2->adress + p2->size) == p3->adress) {//向后合并 //吧p3去掉合并到p2里面去,这个要考虑尾部节点 p2->size += p3->size; if (p3 == tail) {//去除p3 tail = p2; delete p3; p3 == nullptr; } else { p2->next = p3->next; delete p3; p3 = p2->next; } } else if ((p1->adress + p1->size) == p2->adress && (p2->adress + p2->size) == p3->adress) {//前后一起合并,去除p2,p3,考虑尾部节点 p1->size += p2->size + p3->size; if (p3 == tail) { tail = p1; p1->next = nullptr; delete p2, p3; p3 = nullptr; } } else {//什么也不干的类型 //移动一位 p1 = p2; p2 = p3; p3 = p3->next; //整体下移一位 } } } } } //首次循环适应算法的添加,就是尾部添加 //void addNode2(gSize, gAdress) void freeLink::addNode2(int size, int adress) { //直接尾部插入这个回收的节点 //这块内存的起始地址 Node* newNode = new Node(size, adress, 'O', nullptr); tail->next = newNode; tail = newNode; //添加到尾部 } //循环首次适应 //void setNeed(int index); void freeLink::setNeed(int index, int size) { Node* p; Node* p2; //就是要返回的索引对象 p = p2 = head->next; int i = 1; while (i < index) { p = p2; p2 = p2->next; ++i; } p2->size -= size; //把对应的空闲区间的大小修改 p2->adress += size; //新的起始地址 if (p2->size == 0) { if (p2 == tail) { //重置尾节点,并且去除大小为0的节点 delete p2; p->next = nullptr; tail = p; } else { //不是尾部节点,就直接去除大小为0的节点就可以了 p->next = p2->next; delete p2; } } } //删除尾部节点的函数 //void popTail(); void freeLink::popTail() { //要去除尾部节点,就要重新给tail定位 Node* p; Node* p2; p = head; p2 = p->next; while (p2 != tail) { p = p2; p2 = p2->next; //循环直到指向最后一个 } //此时p2指向tail tail = p; delete p2; tail->next = nullptr; } //合并全部空闲的节点 //void heBing(); void freeLink::heBing(int allFreeAdress) { Node* p; Node* p2; p = head; p2 = p->next; int allFreeSize = 0; //统计所有的空闲区间的大小 //int allFreeAdress=0; //得到新的起始地址 while (head != tail) { allFreeSize += tail->size; popTail(); } //此时全部的节点都被删除,为空闲分区链添加一个最大的空间 addNode(allFreeSize, allFreeAdress); } //去除对应的节点 //void popNeed(int index); void freeLink::popNeed(int index) { Node* p; Node* p2; //就是要返回的索引对象 p = p2 = head->next; int i = 1; while (i < index) { p = p2; p2 = p2->next; ++i; } //去除p2 p = p2->next; delete p2; } //得到index部节点的地址 //int getNeedAdress(int index); int freeLink::getNeedAdress(int index) { Node* p; Node* p2; //就是要返回的索引对象 p = p2 = head->next; int i = 1; while (i < index) { p = p2; p2 = p2->next; ++i; } return p2->getAdress(); } //得到第index位的size //int getNeedSize(int index); int freeLink::getNeedSize(int index) { Node* p; Node* p2; //就是要返回的索引对象 p = p2 = head->next; int i = 1; while (i < index) { p = p2; p2 = p2->next; ++i; } return p2->getSize(); } //找到要修改的节点是第几位] //int getNeedGai(size); int freeLink::getNeedGai(int size) { int index = 1; //返回索引 Node* p; Node* p2; p = p2 = head->next; //p2指向要修改的节点 while (p2->size < size || p2 == nullptr) { p = p2; p2 = p2->next; ++index; } if (p2 == nullptr) return 0; return index; //返回当前位置的索引 } //设置第i个节点 //void setHeadNode(int index, int size, int adress); void freeLink::setNode(int index, int size, int adress) { Node* p; Node* p2; //p2指向要修改的节点 p = head; p2 = p->next; for (int i = 1; i < index; ++i) { p = p2; p2 = p2->next; //要修改的对象 } /* p2->size = size; p2->adress = adress; */ //吧原来的节点删除,重新插入到正确的位置 //Node* newPaiXu = new Node(size, adress, 'O', nullptr); if (p2 == tail) { //如果p2是尾节点,那就重置为节点,在插入 delete p2; p->next = nullptr; tail = p; } else { //不是尾部节点那就直接断 p->next = p2->next; delete p2; } //插入 addNode(size, adress); } //显示当前的分区 //void show(); void freeLink::show() { Node* p; p = head->next; cout << "自由分区的链表是(剩余, 起始地址)" << endl; while (p != nullptr) { cout << "(" << p->size << " , " << p->adress << ")->"; p = p->next; } cout << endl; } //内存地址相同的时候的碎片拼接 //void pingJie(); //2014年9月2日17:03:46有问题 void freeLink::pingJie() { Node* p; Node* p2; p = head; //指向头结点 p2 = p->next; //指向第一个节点 //int count=1; int qiShiAdress; //这样来合并,用起始地址加内存的值在链表中找,是不是有节点的起始和他相同,如果相同就向后合并,遍历整个链表 while (p2 != nullptr) { qiShiAdress = p2->adress + p2->size; Node* p2_3 = head; for (Node* p3 = head->next; p3 != nullptr; p3 = p3->next) //p2_3指向p3的前面 { if (qiShiAdress == p3->adress) { //找到了可以合并的那么就直接把这两个节点合并,把找到的这两个去掉重新插入 int newAdress = p2->adress; int newSize = p2->size + p3->size; //这里断掉链表要小心不是紧挨着,断开怎么断? if (p2->next == p3) { p->next = p3->next; } else { p->next = p2->next; p2_3->next = p3->next; } delete p2, p3; p2 = p->next; //Node* chaRu=new Node(newSize, newAdress, 'O', nullptr); this->addNode(newSize, newAdress); qiShiAdress = 0; //重置,作为标准,以便后面判断是否还要到下一个节点 break; } p2_3 = p3; } if (qiShiAdress != 0) { p = p2; p2 = p2->next; } } /* //!2014年9月3日09:19:37 //这里考虑到保持的时候是从小到大,而拼接是按地址重后到前的排序的 //把Node按地址的位置重新排序保存的vector里面去 //先知道一共有多少个节点 while(p2 != nullptr) { p=p2; p2=p2->next; ++count; //当p指向尾节点,那就结束,统计一共有多少个节点 } //重置p,p2 p=head->next; p2=p->next; //直到全部按地址递增的方式全部放入到vector里面去 //然后按地址取出Node,按上面的方式合并 //找到可以拼接的地方进行拼接 //while(p2 != nullptr) //重头找到尾,找到就直接跳出,找不到就到达尾部 //{//可能有多处要合并不止一处 if((p->adress+p->size) == p2->adress) { //如果是末尾的话,要重置尾指针 if(p2 == tail) { tail=p; } //如果有可以合并的区间的话 //1、吧p的内存大小改变成p和p2的内存和 p->size+=p2->size; //2、吧p的指针指向p2的后面 p->next=p2->next; //3、吧p2断开,然后释放p2 delete p2; } p=p2; p2=p2->next; //} //如果是尾部节点的话,那么就是没有可以合并的区间 if(p == tail) {//看是不是只有一个节点 cout<<"xxx"<<endl; } else { while(p->next != tail || (p->adress+p->size) != p2->adress) //找到可以合并的区间,或者到了尾部节点 { //cout<<"xxx"<<endl; p=p2; //吧p和p2整体向前移动一位 p2=p2->next; } if((p->adress+p->size) == p2->adress && p->next == tail) { //如果有可以合并的区间的话 //1、吧p的内存大小改变成p和p2的内存和 p->size+=p2->size; //2、吧p的指针指向p2的后面 p->next=p2->next; //3、吧p2断开,然后释放p2 delete p2; tail=p; //重置尾节点 } } */ } //添加一个Node,等会选择插入的地点 //void addNode(int size, int adress); void freeLink::addNode(int size, int adress) { //1、先找到要插入的位置节点p指向前面的那个节点,p2指向后面那个节点 Node* p; Node* p2; p = head; p2 = head->next; if (p2 != nullptr) { while (p2->size < size) //找到比size要大的第一个节点 { p = p2; p2 = p2->next; if (p == tail) break; } } //判断是不是尾节点,不然要重置尾节点 if (p2 == nullptr) { //如果是尾部节点,那就直接加上去就可以了 Node* p3 = new Node(size, adress, 'O', nullptr); tail->next = p3; //重置尾节点 tail = p3; } else { //2、创建一个节点保存这个内存信息,这个节点插入到p和p2之间 //这块内存的起始地址 Node* newNode = new Node(size, adress, 'O', p2); //3、插入链表 //就是把newNode插入到两点之间 p->next = newNode; } } //删除Node //void popNode(char name); /* freeLink::Node* freeLink::popNode(char name) { //空闲分区删除节点一般是改变节点的大小 //判断是要改变还是要删除 } */ //busyLink类的定义 //合并所有adress回收碎片 //void reAdress(); int busyLink::reAdress() { Node* p; Node* p2; p = head; p2 = p->next; int endAdress = 0; //循环到队尾,size不变,adress全部重置 while (p != tail) { p2->adress = p->adress + p->size; //把这个节点的起始地址改为上个节点的结束 p = p2; p2 = p2->next; //指向下一个 } //当最后一个也得到处理的时候 //重定位结束, //后面再调用freeLink里面的函数,把所有的free节点收集起来做成一个大的空闲节点 endAdress = tail->adress + tail->size; return endAdress; } //得到索引节点的adress //int getNeedAdress(int index); int busyLink::getNeedAdress(int index) { Node* p; Node* p2; //就是要返回的索引对象 p = p2 = head->next; int i = 1; while (i < index) { p = p2; p2 = p2->next; ++i; } //cout<<"p2 name:"<<p2->name<<endl; return p2->adress; //记得加return 返回啊!!!!我的天浪费我半天 } //得到索引节点的size //int getNeedSize(int index); int busyLink::getNeedSize(int index) { Node* p; Node* p2; //就是要返回的索引对象 p = p2 = head->next; int i = 1; while (i < index) { p = p2; p2 = p2->next; ++i; } p2->getSize(); return p2->getSize(); } //得到需要的该的节点的索引 //int getNeedGai(char name); int busyLink::getNeedGai(char name) { int index = 1; //返回索引 Node* p; Node* p2; p = p2 = head->next; //p2指向要修改的节点 while (p2->name != name) { p = p2; p2 = p2->next; ++index; if (p == tail) break; } if (p2 == nullptr) return 0; //cout<<index<<endl; return index; //返回当前位置的索引 } //显示当前的分区 //void show(); void busyLink::show() { Node* p; p = head->next; cout << "作业分区的链表是(剩余, 名字, 起始地址)" << endl; while (p != nullptr) { cout << "(" << p->size << " , " << p->name << " , " << p->adress << ")->"; p = p->next; } cout << endl; } //内存地址相同的时候的碎片拼接 //void pingJie(); //添加一个Node,等会选择插入的地点 //void addNode(int size, int adress, char name); void busyLink::addNode(int size, int adress, char name) { //工作链表添加的作业直接添加到尾部就可以了 Node* p; //创建一个将要进入内存的作业 p = new Node(size, adress, name, nullptr); //其实这里析构函数应该回收p的内存 tail->next = p; tail = p; } //删除Node //void popNode(char name); void busyLink::popNode(char name) { Node* p; Node* p2; //1、找到名字为c的内存 p = p2 = head->next; while (p2->name != name || p2 == nullptr) { p = p2; p2 = p2->next; } if (p2 == nullptr) { std::cout << "不好意思,没有这个作业进入内存" << std::endl; return; } //2、得到这块内存里面的值 //int oldAdd=p2->adress; //int oldsize=p2->size; //3、创建一个节点保存这个内存的值 //Node* p3=new Node(oldsize, oldAdd, name, nullptr); //4、回收原来的这块内存 if (p->next == tail) { delete p2; p->next = nullptr; tail = p; } else { p->next = p2->next; delete p2; } }
原文地址:http://blog.csdn.net/cutter_point/article/details/39077075