【操作系统】Link.cpp

/************************************************************************/
/* 功能:  模拟实现可变分区存储管理的最佳适应算法的链表类
时间: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;
	}
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值