Ruby实现的快排 [Coursera Algorithms: Design and Analysis, Part 1]

Algorithms: Design and Analysis, Part 1 这门课的第二个编程问题。

这一道题要求对比在快排算法中,使用不同的pivot策略所带来的总的比较数的不同。这道题我试了5次才使得所有的结果正确,前边错误主要的问题在于partition算法和课上讲的不一致。

题目要求的选取pivot的方法共分三种:1)选取第一个;2)选取最后一个;3)选取第一个数、最后一个数和位于中间的数这三个数中的中间数(既不是最大也不是最小),分别计算在这三种方法下快排需要进行多少次比较才能完成。在计算比较数的时候,求中间数所需要的比较数不计入内,也就是说排序一个长度为m的子串所需要的比较数是m-1(pivot分别与m-1个数进行比较)

第一次尝试的时候用ruby写了最简单的快排算法:

def qsort1 array 
    if array.size <= 1 
        #长度小于等于1,比较数为0,直接返回
return 0 
    end
    arr = array.dup

    #取第一个为pivot
    pivot = arr.shift

    #把当前arr拆分成比pivot小和比pivot大两部分
    smaller,bigger = arr.partition {|x| x<pivot}
    return qsort1(smaller) + qsort1(bigger) + array.size - 1
end

 

结果全错, 错误原因是arr.partiton的实现与课上所讲的partition的实现不同,于是又去看了看slides:

 

手动实现了一下这个算法,因为实现方法不太一样,细节上有些小差异,导致还调整了几次才过(都是因为不认真看slide……),最终实现代码如下:

def pivot1 array
    #总是取第一个为pivot
    array.shift
end 

def pivot2 array
    #总是取最后一个为pivot,方法是先交换最后一个和第一个数,然后取第一个
    array[0],array[array.size-1] = array[array.size-1],array[0]
    array.shift
end

def pivot3 array
    #取中间数为pivot,不管中间数是哪一个,都把它和第一个数交换
    mp = (array.size + 1)/2 - 1

    h = array[0]
    m = array[mp]
    t = array[array.size-1]

    if (m<h||t<=h)&&(h<=m||h<=t) 
    elsif (h<m||t<m)&&(m<h||m<t)        
        array[0],array[mp] = array[mp],array[0]
    else
        array[0],array[array.size-1] = array[array.size-1],array[0]
    end 

    array.shift
end

def qsort array,type
    # end condition
    if array.size <= 1return 0
    end

    bigger = array.dup

    if type==1
        pivot = pivot1 bigger
    elsif type==2
        pivot = pivot2 bigger
    else
        pivot = pivot3 bigger
    end
    
    i = j = 0
    while j < bigger.size 
        if bigger[j] < pivot
            bigger[i],bigger[j] = bigger[j],bigger[i]
            i += 1
        end
        j += 1
    end

    smaller = bigger.shift(i)
    #因为最后要把smaller的最后一个数同位于第一个位置的pivot交换,所以做一次-1的rotate
    smaller.rotate! -1

    return qsort(smaller, type) + qsort(bigger, type) + array.size - 1
end    

 

 

 

posted @ 2013-07-23 10:56  Zealoct  阅读(303)  评论(0编辑  收藏  举报