利用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限制,表明这是一个类型成员。
相关文章推荐
- 利用scikit-learn下的knn实现kaggle的手写数字识别问题
- 利用C语言实现“百马百担”问题方法示例
- 课程设计——利用信号量实现读-写者问题(JAVA)
- 利用mac地址来验证用户权限实现问题
- 如何利用PopupWindow实现弹出菜单并解决焦点获取以及与软键盘冲突问题
- UE4利用骨骼实现头发摆动(马尾)效果遇见的问题
- 自己实现集合框架(五):利用单链表解决约瑟夫环问题
- 利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题
- Android自定义控件系列八:详解onMeasure()(二)--利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题
- 课程设计——利用信号量实现生产者-消费者问题(java)
- 浅谈移动端的自适应问题——响应式、rem/em、利用Js动态实现移动端自适应
- 利用MFC里面格式化函数也可以实现可变长度的问题
- Android自定义控件系列八:详解onMeasure()(二)--利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题
- 利用HTML5 Canvas和Javascript实现的蚁群算法求解TSP问题演示
- 利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题
- Android利用ViewPager实现图片浏览,解决内存问题
- java利用lock和unlock实现消费者与生产者问题(多线程)
- 【代码练习6】利用多线程生产消费问题实现熊吃蜂蜜问题
- [置顶] 经典利用信号量实现同步的问题
- 利用AVFoundation实现二维码扫描以及其中的问题