Why function template 'among' is of complexity O(1) and not O(n)?
Ali Çehreli
acehreli at yahoo.com
Wed Feb 19 11:45:39 PST 2014
On 02/19/2014 01:46 AM, Gopan wrote:
> On Wednesday, 19 February 2014 at 09:09:25 UTC, Tobias Pankrath wrote:
>> On Wednesday, 19 February 2014 at 08:58:10 UTC, Gopan wrote:
>>> Recently, I came across the following thread
>>> http://forum.dlang.org/thread/l8nocr$1dv5$1@digitalmars.com?page=2
>>>
>>> On Monday, 16 December 2013 at 22:10:52 UTC, Andrei Alexandrescu wrote:
>>>> On 12/16/13 1:45 PM, Walter Bright wrote:
>>>>> On 12/16/2013 12:38 PM, Andrei Alexandrescu wrote:
>>>>>> uint among(T, Us...)(T v, Us vals)
>>>>>> {
>>>>>> foreach (i, U; Us)
>>>>>> {
>>>>>> if (v == vals[i]) return i + 1;
>>>>>> }
>>>>>> return 0;
>>>>>> }
>>>>>
>>>>> This has O(n) behavior, which might be unexpected for the user.
>>>>
>>>> It's O(1) because the data size is in the source text. There's no
>>>> variable n.
>>>
>>> To me, it looks like a Linear Search and hence of complexity O(n).
>>> Could somebody please elaborate why it is O(1) and not O(n)?
>>> If there is an article/document that I am to read to understand this,
>>> please cite it.
>>>
>>> (I am a beginner level programmer and new to D Language.)
>>>
>>> Thanks,
>>> Gopan.
>>
>> It's O(k) with k = vals.length, which is the number of arguments given
>> to the function, which is a compile time constant and not dependent on
>> any input of the final program. In O(n) the n always relates to the
>> input somehow.
>
> I agree that vals.length is known at compile time. But while running
> the application, it iterates through every val in the input list until a
> match is found.
> So, how can that be considered O(1)?
>
> See my test app and output.
>
> uint among(T, Us...)(T v, Us vals)
> {
> foreach (i, U; Us)
> {
> writeln("checking ", v, " == ", vals[i]);
> if (v == vals[i])
> return i + 1;
> }
> return 0;
> }
>
> void main()
> {
> uint index = among(3, 1,2,5,3);
> writeln("Index of 3 in (1,2,5,3) is ", index);
> }
>
> outrput of running the app:
> checking 3 == 1
> checking 3 == 2
> checking 3 == 5
> checking 3 == 3
> Index of 3 in (1,2,5,3) is 4
>
> Or, is my undertanding about Big-O notation of complexity wrong?
You get that output only because you have inserted the writeln()
expressions in there.
That foreach over variadic template arguments is a "compile-time
foreach"[1]. For example, if v were 2 and vals were "1, 2, 3", the
original code would be expanded to the following:
if (2 == 1) return 1; // i == 0
if (2 == 2) return 2; // i == 1
if (2 == 3) return 3; // i == 3
Since all of those conditions is known to be true or false at compile
time, the compiler will reduce the code to the following:
return 2;
Ali
[1] http://ddili.org/ders/d.en/tuples.html
More information about the Digitalmars-d-learn
mailing list