您的位置:首页 > 其它

利用AVL树实现搬箱问题的best fit策略

2014-04-18 11:27 281 查看
//my.h
//定义两个数据类型,货物Goods,箱子Box

#include <vector>
#include <cstddef>
#include <iostream>
struct Goods
{
int id;
double weight;
Goods(int i,double w):id(i),weight(w) { }
~Goods()
{ };
};

struct Box
{
int id;
std::vector<Goods*> vG;
double space;
Box(int i,double f,Goods* x = NULL)
{
id = i;
space = f;
if(x != NULL)
vG.push_back(x);
}

Box& operator-= (Goods& rhs)
{
space -= rhs.weight;
vG.push_back(&rhs);
return *this;
}

Box(Box& rhs)
{
operator=(rhs);
}

Box& operator= (const Box& rhs)
{
if(this == &rhs)
return *this;
id = rhs.id;
space = rhs.space;
vG = rhs.vG;
return *this;
}

~Box()
{
int n = vG.size();
for(int i = 0; i < n; ++i)
delete vG[i];
}

};

bool operator< (const Box& lhs, const Box& rhs)
{
return (lhs.space < rhs.space);
}
bool operator== (const Box& lhs,const Box& rhs)
{
return (lhs.space == rhs.space && lhs.id == rhs.id);
}
bool operator<= (const Box& lhs,const Box& rhs)
{
return !(rhs < lhs);
}
bool operator> (const Box& lhs,int a)
{
return (lhs.space > a);
}
bool operator< (const Box& lhs,const Goods& rhs)
{
return (lhs.space < rhs.weight);
}
bool operator< (const Goods& lhs, const Box& rhs)
{
return (lhs.weight < rhs.space);
}
bool operator== (const Box& lhs,const Goods& rhs)
{
return (lhs.space == rhs.weight);
}

std::ostream& operator<< (std::ostream& out,const Box& b)
{
out << "Box: " << b.id << std::endl;
int n = b.vG.size();
if( n > 0)
{
for(int i = 0; i < n-1; ++i)
out << "\t" << b.vG[i]->id << " " << b.vG[i]->weight << std::endl;
out << "\t" << b.vG[n-1]->id << " " << b.vG[n-1]->weight;
}
return out;
}


//avl.h
//主体部分,建立一个AVL树,实现best fit

#include "my.h"
#include <algorithm>
//#include <utility>

template<class T,class V>
class Avl
{
public:
Avl():root(NULL),len(0) { }
Avl(const Avl& rhs)
{
operator= (rhs);
}

~Avl()
{
makeEmpty();
}
void makeEmpty();

void insert( V* x); //GOODS

const Avl& operator= (const Avl& rhs)
{
if(this == &rhs)
return *this;
Avl temp(rhs);
swap(*this,temp);
return *this;
}

void output()
{
for(int i = 0; i < vT.size(); ++i)
std::cout << *(vT[i]) << std::endl;
output(root);
}
private:
struct Node
{
T* element;
Node *left;
Node *right;
int height;

Node(T* x,Node *lt,Node *rt,int h = 0)
:element(x),left(lt),right(rt),height(h) { }
~Node()
{
delete element;
element = NULL;
}
};
Node *root;
int len;
std::vector<T*> vT;

int height(const Node* t) const
{ return t == NULL ? -1 : t->height; }

void insert(T* x, Node* &t); //BOX
//void insert(V* x, Node* &t); //GOODS
void remove(Node* p,Node* &t);
void percolateDown(Node* t);
Node* find(V* x,Node* t);
Node* findmin(Node* t) const;
Node* findmax(Node* t) const;  //can't use const Node* t
void rotateWithLeftChild(Node* & k2);
void rotateWithRightChild(Node* & k2);
void doubleWithLeftChild(Node* & k3);
void doubleWithRightChild(Node* & k3);
void makeEmpty(Node* & t);
void output(Node* t)
{
if(t != NULL)
{
output(t->left);
output(t->right);
std::cout << *(t->element) << std::endl;
}
}
};

template<class T,class V>
void Avl<T,V>::insert(V* x)
{
Node* t = find(x,root);
if(t != NULL)
{
*(t->element) -= *x;
//t->element->insert(x);
if(*(t->element) > 1e-5)
percolateDown(t);
else
{
Node* p = t;
if(t->right)
p = findmin(t->right);
else
p = findmax(t->left);
remove(p,root);
swap(t->element,p->element);
vT.push_back(p->element);
}
}
else
{
T* b = new Box(len+1,1-x->weight,x);
//b->insert(x);
++len;
insert(b,root);
}

}

template<class T,class V>
void Avl<T,V>::remove(Node* p, Node* & t)
{
if(t == NULL)
return;
else if(*(p->element) < *(t->element))
{
remove(p,t->left);
if(height(t->left) - height(t->right) == -2)
rotateWithRightChild(t);

}
else if(*(t->element) < *(p->element))
{
remove(p,t->right);
if(height(t->left) - height(t->right) == 2)
rotateWithLeftChild(t);
}
else
{
t = t->left != NULL ? t->left : t->right;
p->left = NULL;
p->right = NULL;
return;
}
t->height = max(height(t->left),height(t->right)) + 1;
}

template<class T,class V>
void Avl<T,V>::insert(T* x, Node* &t)
{
if(t == NULL)
t = new Node(x,NULL,NULL);
else if( *x < *(t->element))
{
insert(x,t->left);
if(height(t->left) - height(t->right) == 2)
{
if(*x < *(t->left->element))
rotateWithLeftChild(t);
else
doubleWithLeftChild(t);
}
}
else
{
insert(x,t->right);
if(height(t->right) - height(t->left) == 2)
{
if( *(t->right->element) <= *x)
rotateWithRightChild(t);
else
doubleWithRightChild(t);
}
}
t->height = max(height(t->left),height(t->right)) + 1;
}

template<class T,class V>
typename Avl<T,V>::Node* Avl<T,V>::find(V* x,Node* t)
{
Node* p = NULL;
while(t != NULL)
{
if( *(t->element) < *x)
{
t = t->right;
}
else if( *x < *(t->element))
{
p = t;
t = t->left;
}
else
{
p = t;
break;
}
}
return p;
}

template<class T,class V>
void Avl<T,V>::percolateDown(Node* t)
{
while(t->left != NULL || t->right != NULL)
{
if(t->left != NULL && (*(t->element) < *(t->left->element)))
{
swap(t->element,t->left->element);
t = t->left;
}
else if(t->right != NULL && (*(t->right->element) < *(t->element)))
{
swap(t->element,t->right->element);
t = t->right;
}
else
break;
}
}

template<class T,class V>
typename Avl<T,V>::Node* Avl<T,V>::findmin(Node* t) const  //can't use const Node* t
{
if(t != NULL)
while(t->left != NULL)
t = t->left;
return t;
}

template<class T,class V>
typename Avl<T,V>::Node* Avl<T,V>::findmax(Node* t) const
{
if(t != NULL)
while(t->right != NULL)
t = t->right;
return t;
}

template<class T,class V>
void Avl<T,V>::rotateWithLeftChild(Node* & k2)
{
Node* k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max(height(k2->left),height(k2->right)) + 1;
k1->height = max(height(k1->left),k2->height) + 1;
k2 = k1;
}

template<class T,class V>
void Avl<T,V>::rotateWithRightChild(Node* & k2)
{
Node* k1 = k2->right;
k2->right = k1->left;
k1->left = k2;
k2->height = max(height(k2->left),height(k2->right)) + 1;
k1->height = max(height(k1->left),k2->height) + 1;
k2 = k1;
}

template<class T,class V>
void Avl<T,V>::doubleWithLeftChild(Node* & k3)
{
rotateWithRightChild(k3->left);
rotateWithLeftChild(k3);
}

template<class T,class V>
void Avl<T,V>::doubleWithRightChild(Node* & k3)
{
rotateWithLeftChild(k3->right);
rotateWithRightChild(k3);
}

template<class T,class V>
void Avl<T,V>::makeEmpty()
{
makeEmpty(root);
}

template<class T,class V>
void Avl<T,V>::makeEmpty(Node* & t)
{
if(t != NULL)
{
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
}
t = NULL;
for(int i = 0; i < vT.size(); ++i)
delete vT[i];
}


//main.cpp
/***********************************
装箱问题:利用AVL树
1、实现首次适配算法
2、实现最佳适配算法
作者:陈卫安
时间:2014-04-09
***********************************/
#include "avl.h"
//#include <iostream>
using namespace std;

void inputGoods(vector<Goods*>& G)
{
double w;
int i = 0;
Goods* p = NULL;
while(cin)
{
cin >> w;
p = new Goods(i,w);
G.push_back(p);
i++;
}
}

void FirstFit(Avl<Box,Goods>& boxtree,const vector<Goods*>& G)
{
for(int i = 0; i < G.size(); i++)
boxtree.insert(G[i]);
}

int main()
{
Avl<Box,Goods> boxtree;
vector<Goods*> G;
inputGoods(G);
FirstFit(boxtree,G);
boxtree.output();
return 0;
}


思路:

  1、当树为空时,建立一个新节点(即开辟一个新箱子);

  2、若不为空,寻找最适合的节点(箱子),space = 1 - weight,然后下滤到合适位置;

  3、若箱子容量为0,从树中删除该节点(箱子),存到数组。

  4、若没有找到能够容下该货品的节点(箱子),开辟一个箱子,插入到树里。

编程时遇到的一些问题:

  1、函数形参Node* 前面不能加cosnt,如果加了const,只能传递const类型的数据指针作为实参。这点和传值Node& 不一样,const Node& 表示即可以传const类型的数据,也可以传非const类似的数据。

  2、Node* find() 返回一个类里面定义的数据类型,这是一个类型成员,类似vector<int>::size_type,需要在返回类型前面加类限定符,

  改为 typename Avl<T,V>::Node* find() ;需要在前面加typename限制,表明这是一个类型成员。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐