473,781 Members | 2,702 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

STL: map vs vector

Hi,

This is a follow-up of sort of this thread:
http://groups.google.com/group/comp....2cab752779f1fa

I've been chewing on this problem for a while. When I came across the
above thread, I figured that maybe other members have a better idea on
how to approach this.

I'm currently trying to decide between which one of maps or vectors to
use. I'm trying to come up with a design that will let me perform fast
insertions and deletions (w/o duplicates) in a sorted "list" and then
look up every 25th or so element (and then iterate sequentially for the
next 25 values , so sequential look up). The indexed lookup happens
slightly more frequently than insertions and deletions, so it makes
sense to make lookup efficient. Because the insertions and deletions
also happen often, fast/efficient lookups are helpful as well. Memory
isnt as much of an issue as speed is.

I've looked around a bit, so if this is something that has been
discussed before, please let me know.

Right now I have 2 "solutions" .

One is a sorted vector, where I use 'lower_bound' to get where I should
insert the value and insert it there, and use it to find the value to
remove. Lookups are just normal lookups (thru
my_vector.begin ()+indexSubscri pt ). Most inserts and removals are from
the center of the list, so whenever there is an insertion or removal,
I'm guessing that all the elements are copied up or down. The values
are user defined objects so thats a lot of copying calls.

The other design uses a map and a vector. The map contains the actual
sorted values. The vector is an index to every 25th key which is reset
at every insertion and removal (from the closest previous key in the
map onwards). To access the 25th*x value, you would get the
corresponding key in the index and find it in the map, and then iterate
sequentially.

After implementing both of these, the performance difference is really
minimal for me, but I'm not sure if I'm missing a better way of doing
this. I'm guessing this is something that people have come across
often. I'm a new C++/STL user, so I might be missing a good data
structure to use or a better solution to this problem. Any help would
be appreciated.

Thanks much.
-Z

May 18 '06
13 20163
The whole point of doing this was not having to iterate all the way
down the list.
So the way this is used is that I have a bunch of records. Depending on
the record x used, you would get 25xth to 25(x+1)th . So if there are
multiple records called, for each record you would have to iterate all
the way down the list to get the values. For lists that are in the
thousands, this is very hard. So for imagine this for x = 1000 with x =
1500. Now imagine doing this for 100 or so records all with different x
values. There's a lot of unnecessary iteration going on.
Since insertions or removals might happen 6-7 times a second, it makes
more sense to have an index instead of using +=25 to iterate linearly.
The gains in doing that are substantial.

May 22 '06 #11
In message <11************ **********@j73g 2000cwa.googleg roups.com>, Luke
Meyers <n.***********@ gmail.com> writes

Sorry, I didn't try this myself prior to posting. Whether += is
defined is (perhaps surprisingly at first) kind of irrelevant. You've
got a forward-iterator, which means you've got operator++, so you can
always implement operator+= in terms of that. If the standard library
doesn't provide this, it's probably to avoid implying that the
operation is more efficient than it really is.

Here's a working implementation:
(apart from being UB :-( )
namespace std {
17.4.3.1 It is undefined for a C + + program to add declarations or
definitions to namespace std or namespaces within namespace std unless
otherwise specified. A program may add template specializations for any
standard library template to namespace std. Such a specialization
(complete or partial) of a standard library template results in
undefined behavior unless the declaration depends on a user-defined name
of external linkage and unless the specialization meets the standard
library requirements for the original template.
template <class FwIter>
FwIter &
operator+=(FwI ter & iter, size_t n)
which will attempt to match just about any type for its left operand,
not just set iterators.
{
for (int i = 0; i < n; ++i, ++iter); // no body
return iter;
}
}


The C++ way of doing this is called std::advance().

--
Richard Herring
May 22 '06 #12
za****@gmail.co m wrote:
The whole point of doing this was not having to iterate all the way
down the list.
So the way this is used is that I have a bunch of records. Depending on
the record x used, you would get 25xth to 25(x+1)th . So if there are
multiple records called, for each record you would have to iterate all
the way down the list to get the values. For lists that are in the
thousands, this is very hard. So for imagine this for x = 1000 with x =
1500. Now imagine doing this for 100 or so records all with different x
values. There's a lot of unnecessary iteration going on.
Since insertions or removals might happen 6-7 times a second, it makes
more sense to have an index instead of using +=25 to iterate linearly.
The gains in doing that are substantial.


Unless the creation of the indices introduces overhead equivalent to
the linear-search work you're trying to avoid by creating them. Which
is what I stated. I'm well aware, and said explicitly, that the +=
operation doesn't magically introduce constant-time random access to
std::map. Neither does your scheme. If you've got 6-7
insertions/removals per second, and calculate the set of indices (or a
significant fraction thereof -- half, on average, if they're evenly
distributed) each time, you're doing 6-7 operations with time
complexity that's linear in the size of the map per second. If you're
willing to recalculate the set of indices less often, at the expense of
not spanning exactly 25 elements each time, you can incrementally
reduce this. You didn't respond to my suggestion along these lines,
though.

The asymptotic time-complexities of your current scheme, from my best
understanding of your descriptions, are:

Insert/remove element:
O(n*log(n)) // log(n) for std::map insertion, plus O(n) insertions of
recalculated indices

Access element number x*25, given cached index set:
O(log(n)) // can be improved to O(1) if you use vector<map::ite rator>

Iterate across all elements, 25 at a time, assuming no insert/delete
interruptions:
O(n*log(n)) // O(n) elements accessed, log(n) look up each time. Can
be improved to O(n) if you use vector<map::ite rator>

There's no way you'll get better than O(n) for accessing every 25th
element, since the number of elements you want to actually look at has
cardinality of O(n). The problem is the O(n*log(n)) step on
insert/remove. That's as bad as doing push_back on a vector and
calling std::sort each time you insert. Do you still like this scheme?

Finally, getting back to the original point, it's not accurate to
characterize the += step as "iterating all the way down the list." 25
is a constant. You've got an iterator to one point in the list, and
+=25 involves a constant amount of work to get to the next point you're
interested in. If you want to do this n times (or n/25 times, as it
happens), you're going to have linear-time complexity regardless of
whether your constant-time operation is an efficient random access
(which is not available) or the one I described involving looping over
operator++.

I hope this is more clear. I feel like your response was a little
impolite, incidentally -- I feel I've demonstrated adequate
understanding of asymptotic complexity in this thread not to merit a
remedial explanation of why linear search is inefficient.

Unless you've got some better-than-O(n) way of caching those indices
each time you insert/remove, perform fewer insertions/removals, or
recache your indices far less frequently, you're not going to improve
on O(n*log(n)) here. Given that fact, you might as well give up on
this scheme for a more straightforward O(n*log(n)) scheme (one with a
better constant factor, no doubt), or try approaching the problem from
a different perspective entirely.

According to what you've said, it sounds like perhaps you're
over-valuing random access. You said that, after doing one of these
random accesses, you proceed to iterate over the entire collection
starting at that point (on average, half of the elements), 25 at a
time. That's inherently an O(n) operation, so you wouldn't increase
your big-O even by doing linear search for the starting point. Of
course, the constant factor in that lookup is greater by a factor of
25. But, well, food for thought.

Luke

May 22 '06 #13
Richard Herring wrote:
In message <11************ **********@j73g 2000cwa.googleg roups.com>, Luke
Meyers <n.***********@ gmail.com> writes
Here's a working implementation:


(apart from being UB :-( )


Okay, maybe "working implementation" was too strong a phrase. ;)

What I meant is, I coded it up and compiled it, and it worked in my
case -- to be fair, that's more than you get a lot of the time with ng
code!
namespace std {


17.4.3.1 It is undefined for a C + + program to add declarations or
definitions to namespace std or namespaces within namespace std unless
otherwise specified. A program may add template specializations for any
standard library template to namespace std. Such a specialization
(complete or partial) of a standard library template results in
undefined behavior unless the declaration depends on a user-defined name
of external linkage and unless the specialization meets the standard
library requirements for the original template.


Yeah yeah, ya got me. Thanks for pointing this out. I was aware of
this section of the standard, but had chosen following the example of
an old C++ mentor of mine over adhering to the letter of the standard
in this particular case -- not my usual practice, and I'm now glad to
have considered this and found sufficient reason not to make the
exception. His reasoning for adding things to namespace std had to do
with ADL, and putting operations in the same namespace as the entities
to whose interface they belong. Valid in general, but as I considered
your point I realized that, by introducing a template such as this, I
could interfere with lookups happening internal to my standard library
implementation, which may be part of why this section of the standard
exists.
template <class FwIter>
FwIter &
operator+=(FwI ter & iter, size_t n)


which will attempt to match just about any type for its left operand,
not just set iterators.


Right, and I knew this. Just as you know that writing correct generic
code is full of unique challenges -- my point was not to say, here's
some perfect code you should copy and paste and use everywhere, but
just to point out that based on the ability to increment, incrementing
by 25 is an obvious and trivial extension. How it's accomplished
syntactically, while perhaps interesting in another context, is not
important to the question at hand.
for (int i = 0; i < n; ++i, ++iter); // no body


The C++ way of doing this is called std::advance().


Yes, that's exactly what I wish I had thought of.

Thanks,
Luke

May 22 '06 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

30
2746
by: Przemo Drochomirecki | last post by:
Hi, The task was indeed simple. Read 2.000.000 words (average length = 9), sort them and write it to new file. I've made this in STL, and it was almost 17 times slower than my previous "clear-C-code". I used <vector>, <algorithm>, <iostream> and <algorithm>. Is STL really so slow? Thx in adv. Przemo
9
1889
by: Aguilar, James | last post by:
Hey guys. A new question: I want to use an STL libarary to hold a bunch of objects I create. Actually, it will hold references to the objects, but that's beside the point, for the most part. Here's the question: I want to be able to change the references (including deleting them). Is there any way to do that besides using pointers rather than references for the STL library? I'd also prefer to avoid using const_cast, if it is indeed...
35
2653
by: Jon Slaughter | last post by:
I'm having a problem allocating some elements of a vector then deleting them. Basicaly I have something like this: class base { private: std::vector<object> V;
11
4757
by: ma740988 | last post by:
I'm perusing a slide with roughly 12 bullets spread across 3 pages. Each bullet reflects 'advice'. I'm ok with all but 1 bullet, more specifically the bullet that states: " Avoid the STL unless absolutely necessary " Now, I'm not acclimated with much C++ history, but something tells me this is akin to trepidation that surrounded C++ during it's inception? IOW, is this 'old school' rhetoric or ..... How do you refute this argument?
7
1992
by: rodrigostrauss | last post by:
I'm using Visual Studio 2005 Professional, and I didn't find the STL.NET. This code: #include "stdafx.h" #include <vector> using namespace System; using namespace std; int main(array<System::String ^> ^args)
8
3954
by: Gregory | last post by:
I have a question about using STL containers in C++ class public interface. Lets say that I want to return some container from class method or accept class method parameter as some container. For example: class A { public: const vector<int>& getTable() { return m_table; }
9
4620
by: Christian Chrismann | last post by:
Hi, I've a runtime problem with STL vectors. Here is the simplified version of the code: template <class Tclass A { ... private: vector<T*myvector; typename vector<T*>::itarator mIt;
1
3075
by: krunalbauskar | last post by:
Hi, Explicit instantiation of STL vector demands explicit instantiation of all the templates it using internally. For example - <snippet> #include <iostream> #include <vector>
2
2761
by: Builder | last post by:
How can I import the following COM interface to C#? DECLARE_INTERFACE_(IVertices, IUnknown) { STDMETHOD(get_vertices) (THIS_ vector<POINT>& vertices) PURE; STDMETHOD(set_vertices) (THIS_ vector<POINTvertices) PURE; }; Is it possible to import STL containers to C# at all?
7
3131
by: ademirzanetti | last post by:
Hi there !!! I would like to listen your opinions about inherit from a STL class like list. For example, do you think it is a good approach if I inherit from list to create something like "myList" as in the example below ? #include "Sector.h" using namespace boost;
0
9639
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9474
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10143
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10076
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
6729
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5375
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5507
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3633
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2870
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.