MultiIndex
|
00001 00002 // Copyright 2012 Yandex Artem Babenko 00003 #pragma once 00004 00005 #include "data_util.h" 00006 #include "multitable.hpp" 00007 00012 typedef vector<int> MergedItemIndices; 00013 00022 template<class OrderType, class MetaInfo> 00023 class OrderedListsMerger { 00024 public: 00028 OrderedListsMerger(); 00033 void setLists(const vector<vector<pair<OrderType, MetaInfo> > >& lists); 00039 inline bool GetNextMergedItemIndices(MergedItemIndices* merged_item_indices); 00043 const vector<vector<pair<OrderType, MetaInfo> > >* lists_ptr; 00047 Multitable<char>& GetYieldedItems() { 00048 return yielded_items_indices_; 00049 } 00050 private: 00055 void InsertMergedItemIndicesInHeap(const MergedItemIndices& merged_item_indices); 00060 void UpdatePrioirityQueue(MergedItemIndices& merged_item_indices); 00064 multimap<OrderType, MergedItemIndices> heap_; 00068 Multitable<char> yielded_items_indices_; 00069 }; 00070 00072 00073 template<class OrderType, class MetaInfo> 00074 OrderedListsMerger<OrderType, MetaInfo>::OrderedListsMerger() { 00075 } 00076 00077 template<class OrderType, class MetaInfo> 00078 void OrderedListsMerger<OrderType, MetaInfo>::InsertMergedItemIndicesInHeap(const MergedItemIndices& merged_item_indices) { 00079 OrderType sum = 0; 00080 for(int list_index = 0; list_index < lists_ptr->size(); ++list_index) { 00081 sum += lists_ptr->at(list_index)[merged_item_indices[list_index]].first; 00082 } 00083 heap_.insert(std::make_pair(sum, merged_item_indices)); 00084 } 00085 00086 template<class OrderType, class MetaInfo> 00087 void OrderedListsMerger<OrderType, MetaInfo>::setLists(const vector<vector<pair<OrderType, MetaInfo> > >& lists) { 00088 lists_ptr = &lists; 00089 heap_.clear(); 00090 MergedItemIndices first_item_indices(lists.size()); 00091 for(int list_index = 0; list_index < lists.size(); ++list_index) { 00092 first_item_indices[list_index] = 0; 00093 } 00094 memset(&(yielded_items_indices_.table[0]), 0, yielded_items_indices_.table.size()); 00095 InsertMergedItemIndicesInHeap(first_item_indices); 00096 } 00097 00098 template<class OrderType, class MetaInfo> 00099 void OrderedListsMerger<OrderType, MetaInfo>::UpdatePrioirityQueue(MergedItemIndices& merged_item_indices) { 00100 for(int list_index = 0; list_index < lists_ptr->size(); ++list_index) { 00101 if(merged_item_indices[list_index] >= lists_ptr->at(list_index).size()) { 00102 return; 00103 } 00104 int current_index = merged_item_indices[list_index]; 00105 merged_item_indices[list_index] -= 1; 00106 if(current_index > 0 && !yielded_items_indices_.GetValue(merged_item_indices)) { 00107 merged_item_indices[list_index] += 1; 00108 return; 00109 } else { 00110 merged_item_indices[list_index] += 1; 00111 } 00112 } 00113 InsertMergedItemIndicesInHeap(merged_item_indices); 00114 } 00115 00116 template<class OrderType, class MetaInfo> 00117 inline bool OrderedListsMerger<OrderType, MetaInfo>::GetNextMergedItemIndices(MergedItemIndices* next_merged_item_indices) { 00118 if(heap_.empty()) { 00119 return false; 00120 } 00121 *next_merged_item_indices = heap_.begin()->second; 00122 yielded_items_indices_.SetValue(1, *next_merged_item_indices); 00123 for(int list_index = 0; list_index < lists_ptr->size(); ++list_index) { 00124 next_merged_item_indices->at(list_index) += 1; 00125 UpdatePrioirityQueue(*next_merged_item_indices); 00126 next_merged_item_indices->at(list_index) -= 1; 00127 } 00128 heap_.erase(heap_.begin()); 00129 return true; 00130 } 00131 00132 template class OrderedListsMerger<Distance, PointId>; 00133 template class OrderedListsMerger<Distance, pair<ClusterId, ClusterId> >;