Quick Sort -- Stack overflow

Hi,

Wrote this quick sort routine in AppleScript. Works ok, but only for very small lists? So 6 elements is ok, but 7 bombs with a stack overflow…

Is the stack in AppleScript really so small. Anybody know how I can find out its real size? or indeed change it maybe?


set theList to {1, 2, 7, 4, 1, 9, 2, 3}
set theLast to count (theList)
set theFirst to 1
set theSort to sort(theList, theFirst, theLast)

on sort(theList, theLeft, theRight)
	
	set i to 1
	set j to (count theList)
	--display dialog "left " & i & " right " & j
	set v to item ((theLeft + theRight) div 2) of theList -- pivot
	--display dialog "the v " & v
	repeat while (j > i)
		repeat while (item i of theList < v)
			set i to i + 1
		end repeat
		repeat while (item j of theList > v)
			set j to j - 1
		end repeat
		if (not i > j) then
			tell theList to set {item i, item j} to {item j, item i} -- swap
			set i to i + 1
			set j to j - 1
		end if
	end repeat
	if (theLeft < j) then sort(theList, theLeft, j)
	if (theRight > i) then sort(theList, i, theRight)
end sort

Model: MacBook Pro
AppleScript: AppleScript 2.2.1
Browser: Safari 534.55.3
Operating System: Mac OS X (10.7)

Hi.

At the top of the handler, i should be set to theLeft and j to theRight.

Nigel,

Your a star! Works perfectly now.

Thanks a million.


on quickSort(theList, theLeft, theRight)
	set i to theLeft
	set j to theRight
	set v to item ((theLeft + theRight) div 2) of theList -- pivot
	repeat while (j > i)
		repeat while (item i of theList < v)
			set i to i + 1
		end repeat
		repeat while (item j of theList > v)
			set j to j - 1
		end repeat
		if (not i > j) then
			tell theList to set {item i, item j} to {item j, item i} -- swap
			set i to i + 1
			set j to j - 1
		end if
	end repeat
	if (theLeft < j) then quickSort(theList, theLeft, j)
	if (theRight > i) then quickSort(theList, i, theRight)
end quickSort


Hello!

I customized this quicksort handler, just a tad, to sort on a chosen item in a sublist. the sublists are of course not ragged!


set ml to {{1, "Pettersen"}, {9, "Olavsen"}, {3, "Davidsen"}}

quickSortL(ml, 1, 3, 2)
log ml

on quickSortL(theList, theLeft, theRight, itemNo)
	set i to theLeft
	set j to theRight
	set v to item itemNo of item ((theLeft + theRight) div 2) of theList -- pivot
	repeat while (j > i)
		repeat while (item itemNo of item i of theList < v)
			set i to i + 1
		end repeat
		repeat while (item itemNo of item j of theList > v)
			set j to j - 1
		end repeat
		if (not i > j) then
			tell theList to set {item i, item j} to {item j, item i} -- swap
			set i to i + 1
			set j to j - 1
		end if
	end repeat
	if (theLeft < j) then quickSortL(theList, theLeft, j, itemNo)
	if (theRight > i) then quickSortL(theList, i, theRight, itemNo)
end quickSortL


Hi, McUsr.

It’s possible to write customisable sorts which take “plug-in” customisations. They’re not quite as fast as fully custom-written ones, but they do save having to write full custom sorts for every contingency. You only have to write script objects containing the required comparison processes:

set ml to {{1, "Pettersen"}, {9, "Olavsen"}, {3, "Davidsen"}}

script sortListsByItemI -- Script object which compares items with the same index in two lists.
	property i : missing value
	
	on isGreater(a, b)
		(a's item i > b's item i)
	end isGreater
end script

set sortListsByItemI's i to 2 -- Customise the customiser (!) to compare item 2 of each list.
CustomQuicksort(ml, 1, 3, sortListsByItemI)
log ml

on CustomQuicksort(theList, theLeft, theRight, CustomObj)
	set i to theLeft
	set j to theRight
	set v to item ((theLeft + theRight) div 2) of theList -- pivot
	repeat while (j > i)
		repeat while CustomObj's isGreater(v, item i of theList)
			set i to i + 1
		end repeat
		repeat while CustomObj's isGreater(item j of theList, v)
			set j to j - 1
		end repeat
		if (not i > j) then
			tell theList to set {item i, item j} to {item j, item i} -- swap
			set i to i + 1
			set j to j - 1
		end if
	end repeat
	if (theLeft < j) then CustomQuicksort(theList, theLeft, j, CustomObj)
	if (theRight > i) then CustomQuicksort(theList, i, theRight, CustomObj)
end CustomQuicksort

Since the demise of this site’s ScriptBuilders section, my own collection of sort handlers has wound up here. (Which reminds me, I must update it with my recently written ternary merge sorts!)

Hello NIgel!

:slight_smile: I just didn’t see that way to do it, last night, I just wanted something simple, a comparator object was on my list, but I have seen your handlers, which is something I want to use when I need the speed they give. But honestly, they seem abit complex to implement, that is why I tinkered this one in the first place! Sheer laziness! :smiley:

As for scriptbuilders, I guess the wayback machine works, I use it, when there are links at apple, that have disappeared, like the guidebook, and such! It is very cool if you haven’t used it, you can click on links, and at least on some links, it works like the links was here today

The other factor is, that I am looking for a uniform way to tell handlers to work on an item in a sublist, or the sublist itself. (I guess I won’t be able to generalize that fully anyway, maybe I’ll end up with a combination of item numbers specified, or a swap handler, togetether with the comparator, in order to avoid to much overhead in the handlers)

Thinking of specifying an itemno of 0 to treat simple lists. There is no problem of doing that towards the comparator object. Which is easier than doing it in, for instance the quicksort routine, but what to do with those cases where there are needed more than swapping of sublists, or returning of sublist items, like swapping items between sublists by the handler, that I haven’t figured out yet. But I guess it can be easily dealt with in a swapper handler, in those cases.

An interesting link. Thanks. It didn’t get Scriptbuilders in the short time between the upload of my sorts and the appearance of the “Under Construction” placeholder, but it’s one to remember for possible future use. :slight_smile:

On my HD, Nigel, your “A Dose of Sorts” folder weighs in at about 842KB. If you use Dropbox and have headroom in your 2GB free allowance, you could share that from Dropbox.

Hello!

I don’t think you need that link that much, but for the newer of us; when getting to links that doesn’t exist anymore .It is sent from heaven! I recently wanted to get back to the code in the “GuideBook” at Apple, and it worked like a charm! :slight_smile: