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

  1 //my.h
  2 //定义两个数据类型,货物Goods,箱子Box
  3 
  4 #include <vector>
  5 #include <cstddef>
  7 #include <iostream>
  8 struct Goods
  9 {
 10     int id;
 11     double weight;
 12     Goods(int i,double w):id(i),weight(w) { }
 13     ~Goods()
 14     { };
 15 };
 16 
 17 struct Box
 18 {
 19     int id;
 20     std::vector<Goods*> vG;
 21     double space;
 22     Box(int i,double f,Goods* x = NULL)
 23     {
 24         id = i;
 25         space = f;
 26         if(x != NULL)
 27             vG.push_back(x);
 28     }
 29 
 30     Box& operator-= (Goods& rhs)
 31     {
 32         space -= rhs.weight;
 33         vG.push_back(&rhs);
 34         return *this;
 35     }

42 Box(Box& rhs) 43 { 44 operator=(rhs); 45 } 46 47 48 Box& operator= (const Box& rhs) 49 { 50 if(this == &rhs) 51 return *this; 52 id = rhs.id; 53 space = rhs.space; 54 vG = rhs.vG; 55 return *this; 56 } 57 58 ~Box() 59 { 60 int n = vG.size(); 61 for(int i = 0; i < n; ++i) 62 delete vG[i]; 63 } 64 65 }; 66 67 bool operator< (const Box& lhs, const Box& rhs) 68 { 69 return (lhs.space < rhs.space); 70 } 71 bool operator== (const Box& lhs,const Box& rhs) 72 { 73 return (lhs.space == rhs.space && lhs.id == rhs.id); 74 } 75 bool operator<= (const Box& lhs,const Box& rhs) 76 { 77 return !(rhs < lhs); 78 } 79 bool operator> (const Box& lhs,int a) 80 { 81 return (lhs.space > a); 82 } 83 bool operator< (const Box& lhs,const Goods& rhs) 84 { 85 return (lhs.space < rhs.weight); 86 } 87 bool operator< (const Goods& lhs, const Box& rhs) 88 { 89 return (lhs.weight < rhs.space); 90 } 91 bool operator== (const Box& lhs,const Goods& rhs) 92 { 93 return (lhs.space == rhs.weight); 94 } 95 96 std::ostream& operator<< (std::ostream& out,const Box& b) 97 { 98 out << "Box: " << b.id << std::endl; 99 int n = b.vG.size(); 100 if( n > 0) 101 { 102 for(int i = 0; i < n-1; ++i) 103 out << "\t" << b.vG[i]->id << " " << b.vG[i]->weight << std::endl; 104 out << "\t" << b.vG[n-1]->id << " " << b.vG[n-1]->weight; 105 } 106 return out; 107 }

 

  1 //avl.h
  2 //主体部分,建立一个AVL树,实现best fit
  3 
  4 #include "my.h"
  5 #include <algorithm>
  6 //#include <utility>
  7 
  8 template<class T,class V>
  9 class Avl
 10 {
 11 public:
 12     Avl():root(NULL),len(0) { }
 13     Avl(const Avl& rhs)
 14     {
 15         operator= (rhs);
 16     }
 17 
 18     ~Avl()
 19     {
 20         makeEmpty();
 21     }
 22     void makeEmpty();
 23 
 24     void insert( V* x); //GOODS
 25 
 26     const Avl& operator= (const Avl& rhs)
 27     {
 28         if(this == &rhs)
 29             return *this;
 30         Avl temp(rhs);
 31         swap(*this,temp);
 32         return *this;
 33     }
 34 
 35     void output()
 36     {
 37         for(int i = 0; i < vT.size(); ++i)
 38             std::cout << *(vT[i]) << std::endl;
 39         output(root);
 40     }
 41 private:
 42     struct Node
 43     {
 44         T* element;
 45         Node *left;
 46         Node *right;
 47         int height;
 48 
 49         Node(T* x,Node *lt,Node *rt,int h = 0)
 50             :element(x),left(lt),right(rt),height(h) { }
 51         ~Node()
 52         {
 53             delete element;
 54             element = NULL;
 55         }
 56     };
 57     Node *root;
 58     int len;
 59     std::vector<T*> vT;
 60 
 61     int height(const Node* t) const
 62     { return t == NULL ? -1 : t->height; }
 63     
 64     void insert(T* x, Node* &t); //BOX
 65     //void insert(V* x, Node* &t); //GOODS
 66     void remove(Node* p,Node* &t);
 67     void percolateDown(Node* t);
 68     Node* find(V* x,Node* t);
 69     Node* findmin(Node* t) const;
 70     Node* findmax(Node* t) const;  //can't use const Node* t
 71     void rotateWithLeftChild(Node* & k2);
 72     void rotateWithRightChild(Node* & k2);
 73     void doubleWithLeftChild(Node* & k3);
 74     void doubleWithRightChild(Node* & k3);
 75     void makeEmpty(Node* & t);
 76     void output(Node* t)
 77     {
 78         if(t != NULL)
 79         {
 80             output(t->left);
 81             output(t->right);
 82             std::cout << *(t->element) << std::endl;
 83         }
 84     }
 85 };
 86 
 87 template<class T,class V>
 88 void Avl<T,V>::insert(V* x)
 89 {
 90     Node* t = find(x,root);
 91     if(t != NULL)
 92     {
 93         *(t->element) -= *x;
 94         //t->element->insert(x);
 95         if(*(t->element) > 1e-5)
 96             percolateDown(t);
 97         else
 98         {
 99             Node* p = t;
100             if(t->right)
101                 p = findmin(t->right);
102             else
103                 p = findmax(t->left);
104             remove(p,root);
105             swap(t->element,p->element);
106             vT.push_back(p->element);
107         }
108     }
109     else
110     {
111         T* b = new Box(len+1,1-x->weight,x);
112         //b->insert(x);
113         ++len;
114         insert(b,root);
115     }
116         
117 }
118 
119 template<class T,class V>
120 void Avl<T,V>::remove(Node* p, Node* & t)
121 {
122     if(t == NULL)
123         return;
124     else if(*(p->element) < *(t->element))
125     {
126         remove(p,t->left);        
127         if(height(t->left) - height(t->right) == -2)
128             rotateWithRightChild(t);
129 
130     }
131     else if(*(t->element) < *(p->element))
132     {
133         remove(p,t->right);
134         if(height(t->left) - height(t->right) == 2)
135             rotateWithLeftChild(t);
136     }
137     else
138     {
139         t = t->left != NULL ? t->left : t->right;
140         p->left = NULL;
141         p->right = NULL;
142         return;
143     }
144     t->height = max(height(t->left),height(t->right)) + 1;
145 }
146 
147 template<class T,class V>
148 void Avl<T,V>::insert(T* x, Node* &t)
149 {
150     if(t == NULL)
151         t = new Node(x,NULL,NULL);
152     else if( *x < *(t->element))
153     {
154         insert(x,t->left);
155         if(height(t->left) - height(t->right) == 2)
156         {
157             if(*x < *(t->left->element))
158                 rotateWithLeftChild(t);
159             else
160                 doubleWithLeftChild(t);
161         }
162     }
163     else
164     {
165         insert(x,t->right);
166         if(height(t->right) - height(t->left) == 2)
167         {
168             if( *(t->right->element) <= *x)
169                 rotateWithRightChild(t);
170             else
171                 doubleWithRightChild(t);
172         }
173     }
174     t->height = max(height(t->left),height(t->right)) + 1;
175 }
176 
177 template<class T,class V>
178 typename Avl<T,V>::Node* Avl<T,V>::find(V* x,Node* t)
179 {
180     Node* p = NULL;
181     while(t != NULL)
182     {   
183         if( *(t->element) < *x)
184         {
185             t = t->right;
186         }
187         else if( *x < *(t->element))
188         {
189             p = t;
190             t = t->left;
191         }   
192         else
193         {
194             p = t;
195             break;
196         }
197     }
198     return p;
199 }
200 
201 template<class T,class V>
202 void Avl<T,V>::percolateDown(Node* t)
203 {
204     while(t->left != NULL || t->right != NULL)
205     {
206         if(t->left != NULL && (*(t->element) < *(t->left->element)))
207         {
208             swap(t->element,t->left->element);
209             t = t->left;
210         }
211         else if(t->right != NULL && (*(t->right->element) < *(t->element)))
212         {
213             swap(t->element,t->right->element);
214             t = t->right;
215         }
216         else
217             break;
218     }
219 }
220 
221 template<class T,class V>
222 typename Avl<T,V>::Node* Avl<T,V>::findmin(Node* t) const  //can't use const Node* t
223 {
224     if(t != NULL)
225         while(t->left != NULL)
226             t = t->left;
227     return t;
228 }
229 
230 template<class T,class V>
231 typename Avl<T,V>::Node* Avl<T,V>::findmax(Node* t) const
232 {
233     if(t != NULL)
234         while(t->right != NULL)
235             t = t->right;
236     return t;
237 }
238 
239 template<class T,class V>
240 void Avl<T,V>::rotateWithLeftChild(Node* & k2)
241 {
242     Node* k1 = k2->left;
243     k2->left = k1->right;
244     k1->right = k2;
245     k2->height = max(height(k2->left),height(k2->right)) + 1;
246     k1->height = max(height(k1->left),k2->height) + 1;
247     k2 = k1;
248 }
249 
250 template<class T,class V>
251 void Avl<T,V>::rotateWithRightChild(Node* & k2)
252 {
253     Node* k1 = k2->right;
254     k2->right = k1->left;
255     k1->left = k2;
256     k2->height = max(height(k2->left),height(k2->right)) + 1;
257     k1->height = max(height(k1->left),k2->height) + 1;
258     k2 = k1;
259 }
260 
261 template<class T,class V>
262 void Avl<T,V>::doubleWithLeftChild(Node* & k3)
263 {
264     rotateWithRightChild(k3->left);
265     rotateWithLeftChild(k3);
266 }
267 
268 template<class T,class V>
269 void Avl<T,V>::doubleWithRightChild(Node* & k3)
270 {
271     rotateWithLeftChild(k3->right);
272     rotateWithRightChild(k3);
273 }
274 
275 template<class T,class V>
276 void Avl<T,V>::makeEmpty()
277 {
278     makeEmpty(root);
279 }
280 
281 template<class T,class V>
282 void Avl<T,V>::makeEmpty(Node* & t)
283 {
284     if(t != NULL)
285     {
286         makeEmpty(t->left);
287         makeEmpty(t->right);
288         delete t;
289     }
290     t = NULL;
291     for(int i = 0; i < vT.size(); ++i)
292         delete vT[i];
293 }

 

 1 //main.cpp
 2 /***********************************
 3 装箱问题:利用AVL树
 4 1、实现首次适配算法
 5 2、实现最佳适配算法
 6 作者:陈卫安
 7 时间:2014-04-09
 8 ***********************************/
 9 #include "avl.h"
10 //#include <iostream>
11 using namespace std;
12 
13 void inputGoods(vector<Goods*>& G)
14 {
15     double w;
16     int i = 0;
17     Goods* p = NULL;
18     while(cin)
19     {
20         cin >> w;
21         p = new Goods(i,w);
22         G.push_back(p);
23         i++;
24     }
25 }
26 
27 void FirstFit(Avl<Box,Goods>& boxtree,const vector<Goods*>& G)
28 {
29     for(int i = 0; i < G.size(); i++)
30         boxtree.insert(G[i]);
31 }
32 
33 int main()
34 {
35     Avl<Box,Goods> boxtree;
36     vector<Goods*> G;
37     inputGoods(G);
38     FirstFit(boxtree,G);
39     boxtree.output();
40     return 0;
41 }

 

思路:

  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限制,表明这是一个类型成员。

posted @ 2014-04-18 11:27  搬砖吊死  阅读(395)  评论(0)    收藏  举报