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.
pull/119/head
Tatsuhiro Tsujikawa 2013-08-21 23:46:16 +09:00
parent 252e91e0ac
commit ee2e21150b
1 changed files with 60 additions and 64 deletions

View File

@ -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.