Why Strings as Classes?

Steven Schveighoffer schveiguy at yahoo.com
Tue Aug 26 06:47:25 PDT 2008


"superdan" wrote
> Christopher Wright Wrote:
>
>> superdan wrote:
>> >> class LinkedList(T)
>> >> {
>> >> Node!(T) head;
>> >>
>> >> /** Gets the ith item of the list. Throws: SIGSEGV if i >= length of
>> >> the list. Time complexity: O(N) for a list of length N. This operation
>> >> is provided for completeness and not recommended for frequent use in
>> >> large lists. */
>> >> T opIndex(int i)
>> >> {
>> >> auto current = head;
>> >> while (i)
>> >> {
>> >> current = current.next;
>> >> }
>> >> return current.value;
>> >> }
>> >> }
>> >
>> > oopsies. houston we got a problem here. problem is all that pluggable 
>> > sort business works only if it can count on a constant time opIndex. 
>> > why? because sort has right in its spec that it takes o(n log n) time. 
>> > if u pass LinkedList to it you obtain a nonsensical design that 
>> > compiles but runs afoul of the spec. because with that opIndex sort 
>> > will run in quadratic time and no amount of commentin' is gonna save it 
>> > from that.
>>
>> WRONG!
>> Those sorting algorithms are correct. Their runtime is now O(n^2 log n)
>> for this linked list.
>
> you got the wrong definition of correct. sort became a non-scalable algo 
> from a scalable algo. whacha gonna say next. bubble sort is viable?!?

O(n^2 log n) is still considered solved.  Anything that is not exponential 
is usually considered P-complete, meaning it can be solved in polynomial 
time.  The unsolvable problems are NP-complete, i.e. non-polynomial.  Non 
polynomial usually means n is in one of the exponents, e.g.:

O(2^n).

That being said, it doesn't take a genius to figure out that a standard 
sorting algorithm on a linked list while trying to use random access is 
going to run longer than the same sorting algorithm on a random-access list. 
But there are ways around this.  For instance, you can sort a linked list in 
O(n log n) time with (in pseudocode):

vector v = list; // copy all elements to v, O(n)
v.sort; // O(n lgn)
list.replaceAll(v); // O(n)

So the total is O(2n + n lgn), and we all know you always take the most 
significant part of the polynomial, so it then becomes:

O(n lgn)

Can I have my PhD now? :P

In all seriousness though, with the way you can call functions with arrays 
as the first argument like member functions, it almost seems like they are 
already classes.  One thing I have against having a string class be the 
default, is that you can use substring on a string in D without any heap 
allocation, and it is super-fast.  And I think substring (slicing) is one of 
the best features that D has.

FWIW, you can have both a string class and an array representing a string, 
and you can define the string class to use an array as it's backing storage. 
I do this in dcollections (ArrayList).  If you want the interface, wrap the 
array, if you want the speed of an array, it is accessible as a member. 
This allows you to decide whichever one you want to use.  You can even use 
algorithms on the array like sort by using the member because you are 
accessing the actual storage of the ArrayList.

-Steve 





More information about the Digitalmars-d mailing list