From ee2e21150b276663ed88bc7e5089109f6da60996 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 21 Aug 2013 23:46:16 +0900 Subject: [PATCH] Use std::unordered_map in IndexedList for faster speed Because mingw cross compiler g++-4.6.3 does not support std::unordered_map::emplace and std::deque::emplace, traditional insert member function is used instead. --- src/IndexedList.h | 124 ++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 64 deletions(-) diff --git a/src/IndexedList.h b/src/IndexedList.h index 46d8cea7..4ade3da9 100644 --- a/src/IndexedList.h +++ b/src/IndexedList.h @@ -38,7 +38,7 @@ #include "common.h" #include -#include +#include #include #include @@ -333,9 +333,8 @@ public: typedef KeyType key_type; typedef ValuePtrType value_type; - typedef std::map IndexType; - typedef std::deque > SeqType; + typedef std::unordered_map IndexType; + typedef std::deque> SeqType; @@ -362,13 +361,13 @@ public: // Inserts (|key|, |value|) to the end of the list. If the same key // has been already added, this function fails. This function - // returns true if it succeeds. Complexity: O(logN) + // returns true if it succeeds. Complexity: O(1) bool push_back(KeyType key, ValuePtrType value) { - typename IndexType::iterator i = index_.lower_bound(key); - if(i == index_.end() || (*i).first != key) { - i = index_.insert(i, std::make_pair(key, value)); - seq_.push_back(std::make_pair(i, value)); + auto i = index_.find(key); + if(i == std::end(index_)) { + index_.insert({key, value}); + seq_.emplace_back(key, value); return true; } else { return false; @@ -377,13 +376,13 @@ public: // Inserts (|key|, |value|) to the front of the list. If the same // key has been already added, this function fails. This function - // returns true if it succeeds. Complexity: O(logN) + // returns true if it succeeds. Complexity: O(1) bool push_front(KeyType key, ValuePtrType value) { - typename IndexType::iterator i = index_.lower_bound(key); - if(i == index_.end() || (*i).first != key) { - i = index_.insert(i, std::make_pair(key, value)); - seq_.push_front(std::make_pair(i, value)); + auto i = index_.find(key); + if(i == std::end(index_)) { + index_.insert({key, value}); + seq_.emplace_front(key, value); return true; } else { return false; @@ -397,33 +396,32 @@ public: iterator insert(size_t dest, KeyType key, ValuePtrType value) { if(dest > size()) { - return seq_.end(); + return std::end(seq_); } - typename IndexType::iterator i = index_.lower_bound(key); - if(i == index_.end() || (*i).first != key) { - typename SeqType::iterator j = seq_.begin(); + auto i = index_.find(key); + if(i == std::end(index_)) { + auto j = std::begin(seq_); std::advance(j, dest); - i = index_.insert(i, std::make_pair(key, value)); - j = seq_.insert(j, std::make_pair(i, value)); - return iterator(j); + index_.insert({key, value}); + return iterator(seq_.insert(j, {key, value})); } else { - return iterator(seq_.end()); + return iterator(std::end(seq_)); } } // Inserts (|key|, |value|) to the position |dest|. If the same key // has been already added, this function fails. This function // returns the iterator to the newly added element if it is - // succeeds, or end(). Complexity: O(logN) if inserted to the first - // or last, otherwise O(N) + // succeeds, or end(). Complexity: O(1) if inserted to the first or + // last, otherwise O(N) iterator insert(iterator dest, KeyType key, ValuePtrType value) { - typename IndexType::iterator i = index_.lower_bound(key); - if(i == index_.end() || (*i).first != key) { - i = index_.insert(i, std::make_pair(key, value)); - return iterator(seq_.insert(dest.p, std::make_pair(i, value))); + auto i = index_.find(key); + if(i == std::end(index_)) { + index_.insert({key, value}); + return iterator(seq_.insert(dest.p, {key, value})); } else { - return iterator(seq_.end()); + return iterator(std::end(seq_)); } } @@ -437,14 +435,14 @@ public: std::vector v; v.reserve(std::distance(first, last)); for(; first != last; ++first) { - KeyType key = keyFunc(*first); - typename IndexType::iterator i = index_.lower_bound(key); - if(i == index_.end() || (*i).first != key) { - i = index_.insert(i, std::make_pair(key, *first)); - v.push_back(std::make_pair(i, *first)); + auto key = keyFunc(*first); + auto i = index_.find(key); + if(i == std::end(index_)) { + index_.insert({key, *first}); + v.emplace_back(key, *first); } } - seq_.insert(dest.p, v.begin(), v.end()); + seq_.insert(dest.p, std::begin(v), std::end(v)); } template @@ -457,14 +455,14 @@ public: std::vector v; v.reserve(std::distance(first, last)); for(; first != last; ++first) { - KeyType key = keyFunc(*first); - typename IndexType::iterator i = index_.lower_bound(key); - if(i == index_.end() || (*i).first != key) { - i = index_.insert(i, std::make_pair(key, *first)); - v.push_back(std::make_pair(i, *first)); + auto key = keyFunc(*first); + auto i = index_.find(key); + if(i == std::end(index_)) { + index_.insert({key, *first}); + v.emplace_back(key, *first); } } - seq_.insert(seq_.begin() + pos, v.begin(), v.end()); + seq_.insert(std::begin(seq_) + pos, std::begin(v), std::end(v)); } // Removes |key| from the list. If the element is not found, this @@ -472,13 +470,12 @@ public: // succeeds. Complexity: O(N) bool remove(KeyType key) { - typename IndexType::iterator i = index_.find(key); - if(i == index_.end()) { + auto i = index_.find(key); + if(i == std::end(index_)) { return false; } - for(typename SeqType::iterator j = seq_.begin(), eoj = seq_.end(); - j != eoj; ++j) { - if((*j).first == i) { + for(auto j = std::begin(seq_), eoj = std::end(seq_); j != eoj; ++j) { + if((*j).first == key) { seq_.erase(j); break; } @@ -502,13 +499,13 @@ public: template void remove_if(Pred pred) { - typename SeqType::iterator first = seq_.begin(), last = seq_.end(); + auto first = std::begin(seq_), last = std::end(seq_); for(; first != last && !pred((*first).second); ++first); if(first == last) { return; } index_.erase((*first).first); - typename SeqType::iterator store = first; + auto store = first; ++first; for(; first != last; ++first) { if(pred((*first).second)) { @@ -522,14 +519,13 @@ public: // Removes element at the front of the list. If the list is empty, // this function fails. This function returns true if it - // succeeds. Complexity: O(logN) + // succeeds. Complexity: O(1) bool pop_front() { if(seq_.empty()) { return false; } - typename IndexType::iterator i = seq_.front().first; - index_.erase(i); + index_.erase(seq_.front().first); seq_.pop_front(); return true; } @@ -545,17 +541,17 @@ public: // O(N) ssize_t move(KeyType key, ssize_t offset, OffsetMode how) { - typename IndexType::iterator idxent = index_.find(key); - if(idxent == index_.end()) { + auto idxent = index_.find(key); + if(idxent == std::end(index_)) { return -1; } - typename SeqType::iterator x = seq_.begin(), eseq = seq_.end(); + auto x = std::begin(seq_), eseq = std::end(seq_); for(; x != eseq; ++x) { - if((*x).first == idxent) { + if((*x).first == (*idxent).first) { break; } } - ssize_t xp = std::distance(seq_.begin(), x); + ssize_t xp = std::distance(std::begin(seq_), x); ssize_t size = index_.size(); ssize_t dest; if(how == OFFSET_MODE_CUR) { @@ -574,7 +570,7 @@ public: } dest = std::max(dest, static_cast(0)); } - typename SeqType::iterator d = seq_.begin(); + auto d = std::begin(seq_); std::advance(d, dest); if(xp < dest) { std::rotate(x, x+1, d+1); @@ -585,11 +581,11 @@ public: } // Returns the value associated by |key|. If it is not found, - // returns ValuePtrType(). Complexity: O(logN) + // returns ValuePtrType(). Complexity: O(1) ValuePtrType get(KeyType key) const { - typename IndexType::const_iterator idxent = index_.find(key); - if(idxent == index_.end()) { + auto idxent = index_.find(key); + if(idxent == std::end(index_)) { return ValuePtrType(); } else { return (*idxent).second; @@ -608,22 +604,22 @@ public: iterator begin() { - return iterator(seq_.begin()); + return iterator(std::begin(seq_)); } iterator end() { - return iterator(seq_.end()); + return iterator(std::end(seq_)); } const_iterator begin() const { - return const_iterator(seq_.begin()); + return const_iterator(std::begin(seq_)); } const_iterator end() const { - return const_iterator(seq_.end()); + return const_iterator(std::end(seq_)); } // Removes all elements from the list.