Browse Source

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.
Tatsuhiro Tsujikawa 12 years ago
parent
commit
ee2e21150b
1 changed files with 60 additions and 64 deletions
  1. 60 64
      src/IndexedList.h

+ 60 - 64
src/IndexedList.h

@@ -38,7 +38,7 @@
 #include "common.h"
 
 #include <deque>
-#include <map>
+#include <unordered_map>
 #include <vector>
 #include <algorithm>
 
@@ -333,9 +333,8 @@ public:
 
   typedef KeyType key_type;
   typedef ValuePtrType value_type;
-  typedef std::map<KeyType, ValuePtrType> IndexType;
-  typedef std::deque<std::pair<typename IndexType::iterator,
-                               ValuePtrType> > SeqType;
+  typedef std::unordered_map<KeyType, ValuePtrType> IndexType;
+  typedef std::deque<std::pair<KeyType, ValuePtrType>> 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<typename SeqType::value_type> 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<typename KeyFunc, typename InputIterator>
@@ -457,14 +455,14 @@ public:
     std::vector<typename SeqType::value_type> 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<typename Pred>
   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<ssize_t>(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.