標籤:作業系統 冒泡排序 演算法 遍曆 鏈表
/************************************************************************//* 功能: 類比實現可變分區儲存管理的最佳適應演算法的鏈表類時間: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){//去除p3tail = 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指向tailtail = 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;}//去除p2p = 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裡面去//Crowdsourced Security Testing道一共有多少個節點while(p2 != nullptr){p=p2;p2=p2->next;++count; //當p指向尾節點,那就結束,統計一共有多少個節點}//重設p,p2p=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斷開,然後釋放p2delete 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斷開,然後釋放p2delete 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;}}
【作業系統】Link.cpp