473,770 Members | 2,096 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

STL list.size() operation - O(1) or O(n) ?

Hi,

I have had trouble determining whether the STL list.size() operation
is O(1) or O(n). I know the list is a doubly-linked list, so if the
size() operation begins at the head, then counts to the end -
obviously its O(n). However, keeping track of inserts and deletes
isn't that tough, so its conceivable (to me!) that size() could be
O(1). For my application, the lists can be quite long (millions of
elements), so the answer greatly impacts my design decisions.

OR is this compiler dependent? (I am using gcc 3.2.2.)

Thanks, Brett
Jul 19 '05 #1
12 10951
"Brett L. Moore" <br*********@tt u.edu> wrote...
I have had trouble determining whether the STL list.size() operation
is O(1) or O(n). I know the list is a doubly-linked list, so if the
size() operation begins at the head, then counts to the end -
obviously its O(n). However, keeping track of inserts and deletes
isn't that tough, so its conceivable (to me!) that size() could be
O(1).
Actually, the Standard requires it to be of constant complexity.
See table 65 and "Notes" after it.
For my application, the lists can be quite long (millions of
elements), so the answer greatly impacts my design decisions.

OR is this compiler dependent? (I am using gcc 3.2.2.)


No, it should not be compiler-dependent.

Victor
Jul 19 '05 #2

"Victor Bazarov"
"Brett L. Moore"
I have had trouble determining whether the STL list.size() operation
is O(1) or O(n). I know the list is a doubly-linked list, so if the
size() operation begins at the head, then counts to the end -
obviously its O(n). However, keeping track of inserts and deletes
isn't that tough, so its conceivable (to me!) that size() could be
O(1).


Actually, the Standard requires it to be of constant complexity.
See table 65 and "Notes" after it.

Are you sure? This would forsake constant time splicing. This does not
correspond with waht Iread in Effective STL Item 4.

For my application, the lists can be quite long (millions of
elements), so the answer greatly impacts my design decisions.

OR is this compiler dependent? (I am using gcc 3.2.2.)


No, it should not be compiler-dependent.

Again this does not correspond with what I read in Effective STL Item 4.

Fraser.
Jul 19 '05 #3
In article <12************ **************@ posting.google. com>, Brett L.
Moore <br*********@tt u.edu> wrote:

| Hi,
|
| I have had trouble determining whether the STL list.size() operation
| is O(1) or O(n). I know the list is a doubly-linked list, so if the
| size() operation begins at the head, then counts to the end -
| obviously its O(n). However, keeping track of inserts and deletes
| isn't that tough, so its conceivable (to me!) that size() could be
| O(1). For my application, the lists can be quite long (millions of
| elements), so the answer greatly impacts my design decisions.
|
| OR is this compiler dependent? (I am using gcc 3.2.2.)

It is compiler dependent (unfortunately) .

The standard says this about size() on all of the containers:

| should have constant complexity

And actually the same note applies to the member swap function, and the
max_size() member function.

The "should" in the above quote does not mean "must". In standardeze
it means "maybe, maybe not".

In the case of list::swap, there are some implementations that have
O(N) size. I'm not positive, but I think gcc may be one of them. I
believe Dinkumware, and I know Metrowerks have a constant complexity
list::size().

The subject has been debated on and off again over the years on
comp.std.c++. You might try a search of that newsgroup for the words
"list", "size" and maybe "complexity " for more information.

A constant time size() forsake's constant time splicing in one out of
the 5 possible splicing situations: splicing some elements from
another list. That operation is (probably) O(some) if size is O(1).
And the constant on the O(some) is quite small. The other 4 splicing
situations remain O(1) even with an O(1) size:

splice one from self
splice one from other
splice some from self
splice all from other

--
Howard Hinnant
Metrowerks
Jul 19 '05 #4
Brett L. Moore wrote:
...
I have had trouble determining whether the STL list.size() operation
is O(1) or O(n). I know the list is a doubly-linked list, so if the
size() operation begins at the head, then counts to the end -
obviously its O(n). However, keeping track of inserts and deletes
isn't that tough, so its conceivable (to me!) that size() could be
O(1). For my application, the lists can be quite long (millions of
elements), so the answer greatly impacts my design decisions.

OR is this compiler dependent? (I am using gcc 3.2.2.)
...


This issue has been discussed at length in comp.std.c++. Try googling
for it.

In short - yes, it is implementation dependent. An implementation might
choose to count list elements, thus making 'list<>::size' an O(1)
operation, but the complexity of list-into-list splice will become O(n)
in this case. Or it might choose to implement this splice as an O(1)
operation, paying for it by O(n) for 'list<>::size'.

--
Best regards,
Andrey Tarasevich
Brainbench C and C++ Programming MVP

Jul 19 '05 #5
"Fraser Ross" <fraserATmember s.v21.co.united kingdom> wrote in message news:<3f******@ news.greennet.n et>...
"Victor Bazarov"
"Brett L. Moore"
I have had trouble determining whether the STL list.size() operation
is O(1) or O(n). I know the list is a doubly-linked list, so if the
size() operation begins at the head, then counts to the end -
obviously its O(n). However, keeping track of inserts and deletes
isn't that tough, so its conceivable (to me!) that size() could be
O(1).


Actually, the Standard requires it to be of constant complexity.
See table 65 and "Notes" after it.

Are you sure? This would forsake constant time splicing. This does not
correspond with waht Iread in Effective STL Item 4.


It doesn't have to I don't think... You could probably rig it so that
when you insert or remove something a counter in the list class is
incremented or decremented. I don't know if that's actually how it's
done, but it would probably be possible.
Jul 19 '05 #6
Evan wrote:
...
It doesn't have to I don't think... You could probably rig it so that
when you insert or remove something a counter in the list class is
incremented or decremented. I don't know if that's actually how it's
done, but it would probably be possible.
...


The problem is that when you splice a range of elements into a list you
don't know the number of elements being inserted. And you don't really
need to know it (which gives you a O(1) splicing), unless you want to
update the element counter on-the-fly. If you choose to do the latter,
you'll have to cope with the range-into-list splice being an O(n)
operation.

It is a trade-off. The implementation is forced to make a choice.

--
Best regards,
Andrey Tarasevich
Brainbench C and C++ Programming MVP

Jul 19 '05 #7
On Fri, 11 Jul 2003 14:52:33 -0700, Andrey Tarasevich <an************ **@hotmail.com> wrote:
Evan wrote:
...
It doesn't have to I don't think... You could probably rig it so that
when you insert or remove something a counter in the list class is
incremented or decremented. I don't know if that's actually how it's
done, but it would probably be possible.
...


The problem is that when you splice a range of elements into a list you
don't know the number of elements being inserted. And you don't really
need to know it (which gives you a O(1) splicing), unless you want to
update the element counter on-the-fly. If you choose to do the latter,
you'll have to cope with the range-into-list splice being an O(n)
operation.

It is a trade-off. The implementation is forced to make a choice.


Yes, but there are more choices than (A) counting the elements in the
range when the splice is done, or (B) counting the elements in the
result list every time its size is requested. For example, (C) keeping
track of whether the size of a list is known or not, updating a known
size whenever it can be done in constant time.

Option (C) would defer a potentially very costly operation until it's
actually needed, which with luck might be never.

With option (C) size() would in general be O(1), unless you've recently
spliced range of elements into the list (say) and not requested the list
size after that, in which case it would be O(n); I'm not sure of the
amortization involved here, it feels complicated whereas the concept is
very simple.

What it illustrates is, I believe, a design _defect_: the arguments
of list::splice do not seem to offer (the implementation) any way to pass
in the size of the range although that size might well be known by the
client code.

The decision seems to have been to "go safe" with a very low-
level and general specification of a range. I think "go safe" is not
compatible with a very low-level and general specification. In short,
I think that that choice (efficiency versus safety) should be the
library user's decision to make, not something forced and frozen,
especially since there are so many other ways of introducing bugs.
Cheers,

- Alf

Jul 19 '05 #8
Stuart Golodetz wrote:
> ...
> I have had trouble determining whether the STL list.size() operation
> is O(1) or O(n). I know the list is a doubly-linked list, so if the
> size() operation begins at the head, then counts to the end -
> obviously its O(n). However, keeping track of inserts and deletes
> isn't that tough, so its conceivable (to me!) that size() could be
> O(1). For my application, the lists can be quite long (millions of
> elements), so the answer greatly impacts my design decisions.
>
> OR is this compiler dependent? (I am using gcc 3.2.2.)
> ...


This issue has been discussed at length in comp.std.c++. Try googling
for it.

In short - yes, it is implementation dependent. An implementation might
choose to count list elements, thus making 'list<>::size' an O(1)
operation, but the complexity of list-into-list splice will become O(n)
in this case. Or it might choose to implement this splice as an O(1)
operation, paying for it by O(n) for 'list<>::size'.


Why not have a flag noting whether or not a list-into-list splice has been
carried out since the last call to size? Then if splices were never carried
out, size would always be O(1), otherwise size would be O(n) for the call
after the splice only, and then O(1) again. Then the cost of recalculating
the size would be deferred until the next size call (i.e. you don't pay for
recalculating the size unless you actually need to) and size's complexity
would remain O(1) if you never did list-into-list splices (i.e. you don't
pay for splicing if you don't use it). I don't know if any actual
implementations do it this way?
...


That would be a perfectly reasonable implementation technique. It won't
change the formal complexity of these operations in general case, of
course, but for most practical cases this approach looks very
attractive. As I said before, this issue has already been discussed
before. And not once.

--
Best regards,
Andrey Tarasevich
Brainbench C and C++ Programming MVP

Jul 19 '05 #9
In article <3f************ ***@News.CIS.DF N.DE>, Alf P. Steinbach
<al***@start.no > wrote:

| What it illustrates is, I believe, a design _defect_: the arguments
| of list::splice do not seem to offer (the implementation) any way to pass
| in the size of the range although that size might well be known by the
| client code.
|
| The decision seems to have been to "go safe" with a very low-
| level and general specification of a range. I think "go safe" is not
| compatible with a very low-level and general specification. In short,
| I think that that choice (efficiency versus safety) should be the
| library user's decision to make, not something forced and frozen,
| especially since there are so many other ways of introducing bugs.

Agreed. It would be great to add an additional splice signature:

void splice(iterator position, list& x, iterator first, iterator last,
size_type n);

Precondition: n == distance(first, last)

I reviewed the places I'm using splice: Most of the time I'm splicing
in an entire list, so this isn't an issue (it's always constant time).
But in one place I'm splicing in a range. And in that particular
example, I already know n before I call splice. It is a waste to have
list::splice recompute it.

-----------

Another aspect of this eternal debate that usually gets neglected is
that an O(1) size can also aid several other list operations. It
doesn't actually change the complexity of any of these other functions,
but it does make them faster (sometimes significantly so), or enable
strong exception safety in some circumstances:

resize
operator==
operator!=
operator=
assign
maybe sort

For example, in resize you just have to flat out compute size if you
don't already have it, so that you can decide whether you want to
append or erase.

In operator== you can check size first (if it is O(1)) and avoid the
element to element compare if the size's are different.

In operator= and assign you can use O(1) size to bump the exception
safety from basic to strong if T::operator= doesn't throw, at no
addtional computational or memory expense, while at the same time
recycling existing nodes as needed.

-----------

On the "lazy-size" concept: It seems to me like a significant amount
of logic/checking/code in order to avoid this one operation under

void splice(iterator position, list& x, iterator first, iterator last)
{
...
size_type delta_size = distance(first, last);
...
}

When you take into account increased code size, possibly increased
per-container overhead, and possible increased run-time checking in
most of the other list members, it seems like a heavy price to pay just
to avoid computing the distance between first and last in this one
function (which the standard says has linear complexity).

-----------

<shrug> The standard says that list::size() /should/ have constant
complexity. It also says that deque::size() /should/ have constant
complexity. Can you imagine the noise it would generate if someone
decided to ship a deque (or vector or string or map) with a size()
function that was O(N)?

Personally I would rather get a compile time error if list::size() was
O(N). At least then I would know that I need to distance(l.begi n(),
l.end()) and the computational cost would be clear and explicit. Same
logic goes against list::operator[](size_type). It would be easy to
implement, but unexpectedly expensive.

-----------

All that being said, I'd still love to see:

void splice(iterator position, list& x,
iterator first, iterator last, size_type n);

Precondition: n == distance(first, last)

as an addition to the existing interface. I believe such an addition
would settle this debate once and for all. And then we could make
std::container: :size() O(1), instead of "should be" O(1).

--
Howard Hinnant
Metrowerks
Jul 19 '05 #10

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

Similar topics

5
1325
by: aruna | last post by:
How do I check the size of int on a machine before runtime, at the pre-processor stage? Is it possible?
1
6379
by: abc my vclass | last post by:
How to fix the height size of Panel1 on SplitContainer?
3
4760
by: Henrik | last post by:
I need to get a list of clickable objects on the desktop and their positions. I have written a small program in C# and by using the Win32 function: WindowFromPoint -function I get a handle to the desktop but now I'm stuck. For those who need to see the code -look below IntPtr hWnd = Win32.WindowFromPoint(Cursor.Position); With the handle I can get alot of cool information such as: Caption,
1
2909
by: lecnac | last post by:
Here's some details: Server and workstation both in the same workgroup Logged into server as local Administrator Logged into workstation as a local user that is only in the Users group The local user on the workstation is also defined with same name and password on the server (and only in the Users group on the server) Server is Windows Server 2003 running IIS 6.0 Workstation is Windows XP Professional ASP.NET 2.0 (C#) web site
1
3704
by: lecnac | last post by:
Sorry for the repost. I must have done something wrong when I tried to post my reply (I can't seem to find it). Anyway, I'd really appreciate any help that anyone could provide. My issue is quickly becoming more and more urgent. I've tried the code below using the server's local Administrator user name and password. This gets me past the Access denied error but gives me a User
5
2496
by: cjt22 | last post by:
Hi there I am fairly new to Python and have not really used regular expressions before (I think this might be needed for my query) and wondered if you could help I have a step class and store in a list step instances A step instance contains variables: name, startTime etc and startTime is stored as a string %H:%M:%S
19
5428
by: Juha Nieminen | last post by:
If I'm not completely mistaken, the only reason why std::list::size() may be (and usually is) a linear-time operation is because they want std::list::splice() to be a constant-time operation, and if you execute the latter, the size of the resulting lists cannot be known without explicitly counting the sizes of the new lists. I was thinking: What if size() was an O(n) operation only *after* a splice() operation has been performed (and...
1
3776
by: kurtzky | last post by:
Hello. Good day. I have this problem with my current program right now. I have a separate report created in Seagate Crystal Reports, and I'm integrating it to my program in C#. I'm using CrystalDecisions and calls the ReportDocument class. Under that report, I have many subreports. What I want to do is to select ALL the fields in the MAIN report and put it in the DataTable, then I would put that DataTable as the DataSource of my...
1
4437
by: venkat chitta | last post by:
Hi All, I want to know how to get a list of all indexes created on a column of a table in PostgreSQL. There is a program block in our application which do this in oracle, now i want to write the same piece of code which works for PostgreSQL as well. So, i want the list of indexes on a column of a table if i know the column name at that time or list of all the indexes on all the columns of the given table. Below is the java Code written for...
0
9618
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
9454
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
9906
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8933
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7456
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6712
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
5354
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
5482
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
2850
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.