大型排序数组的Forth快速排序问题

时间:2016-08-18 18:53:46

标签: forth gforth

我使用Quicksort对整数进行排序,这些整数是由堆栈上的条目表示的集合中的元素。它可以正常工作,除非它必须排序更大(大约10,000个元素)的集合,这些集合恰好已经被分类。

: adswap \ ad1 ad2 -- 
  over @ over @ swap rot ! swap ! ; 

: singlepart \ ad1 ad2 -- ad
  tuck 2dup @ locals| p ad | swap                \ ad2 ad2 ad1
  do i @ p <                                     \ ad2 flag
     if ad i adswap ad cell + to ad then cell    \ ad2 cell
  +loop ad adswap ad ;                           \ ad 

: qsort \ ad1 ad2 --      pointing on first and last cell in array
  2dup < 
  if 2dup singlepart >r
     swap r@ cell - recurse
     r> cell + swap recurse 
  else 2drop 
  then ; 

它可能在返回堆栈中溢出吗?当阵列排序与否时,程序几乎不可能保持跟踪,那么如何解决问题呢?

1 个答案:

答案 0 :(得分:4)

是的,Quicksort被认为是天真实现中边缘情况下返回堆栈溢出的主题。解决方案也是已知的:使用较小的部分进行递归,使用另一部分进行尾部调用。哦,this recipe已在维基百科中描述过:

  

为了确保最多使用O(log n)空间,首先递归到   分区较小的一侧,然后使用尾部调用递归   另一个。

尾调用优化将调用转换为跳转,因此它不使用返回堆栈。

更新了qsort定义:

: qsort \ ad1 ad2 --      pointing on first and last cell in array
  begin
    2dup < 0= if 2drop exit then
    2dup - negate 1 rshift >r \ keep radius (half of the distance)
    2dup singlepart 2dup - >r >r \ ( R: radius distance2 ad )
    r@ cell - swap r> cell+ swap \ ( d-subarray1 d-subarray2 )
    2r> u< if 2swap then recurse \ take smallest subarray first
  again \ tail call optimization by hand
;