算法导论 python代码 第七章

# author Ttssxuan
# chapter 7.1
# the quicksort algorithm

def quicksort(arr, p, r):
    '''
    using the quicksort algorithm to sort the arr[p..r]

    Parameters:
        arr - the array need to be sorted
        p - the beginning index
        r - the ending index
    Returns:
        none
    '''
    if p < r:
        # get the partition point of the arr
        q = partition(arr, p, r)
        # sort the left part
        quicksort(arr, p, q - 1)
        # sort the right part
        quicksort(arr, q + 1, r)


def partition(arr, p, r):
    '''
    divide the arr[p..r] into two parts, the left less than arr[r], the right
    greater than the arr[r]

    Parameters:
        arr - the array need to be sorted
        p - the beginning index
        r - the ending index
    Returns:
        the partition place of the arr
    '''
    x = arr[r]
    i = p - 1
    # divide the arr
    for j in range(p, r):
        if arr[j] <= x:
            i += 1
            arr[i], arr[j] = arr[j], arr[i]
    # exchange the arr[r] to the right position
    arr[i + 1], arr[r] = arr[r], arr[i + 1]
    return i + 1


def partition_same_optimize(arr, p, r):
    '''
    divide the arr[p..r] into two parts, the left less than arr[r], the right
    greater than the arr[r]
    this optimize the the result when all elements in the arr[p..r] is the same

    Parameters:
        arr - the array need to be sorted
        p - the beginning index
        r - the ending index
    Returns:
        the partition place of the arr
    '''
    x = arr[r]
    i = p - 1
    # divide the arr
    for j in range(p, r):
        if arr[j] <= x:
            i += 1
            arr[i], arr[j] = arr[j], arr[i]
    # exchange the arr[r] to the right position
    if arr[p] == arr[r-1] == arr[r]:
        return (p + r) >> 1
    else:
        arr[i + 1], arr[r] = arr[r], arr[i + 1]
        return i + 1


def quicksort_nonincreasing(arr, p, r):
    '''
    using the quicksort algorithm to sort the arr[p..r]
    this is the nonincrease version

    Parameters:
        arr - the array need to be sorted
        p - the beginning index
        r - the ending index
    Returns:
        none
    '''
    if p < r:
        # get the partition point of the arr
        q = partition_nonincreasing(arr, p, r)
        # sort the left part
        quicksort_nonincreasing(arr, p, q - 1)
        # sort the right part
        quicksort_nonincreasing(arr, q + 1, r)


def partition_nonincreasing(arr, p, r):
    '''
    divide the arr[p..r] into two parts, the left less than arr[r], the right
    greater than the arr[r]
    this is the nonincrease version

    Parameters:
        arr - the array need to be sorted
        p - the beginning index
        r - the ending index
    Returns:
        the partition place of the arr
    '''
    x = arr[r]
    i = p - 1
    # divide the arr
    for j in range(p, r):
        if arr[j] >= x:
            i += 1
            arr[i], arr[j] = arr[j], arr[i]
    # exchange the arr[r] to the right position
    arr[i + 1], arr[r] = arr[r], arr[i + 1]
    return i + 1


def randomized_partition(arr, p, r):
    '''
    randomized the partition by exchange arr[r] with a random place

    Parameters:
        arr - the array need to be sorted
        p - the beginning index
        r - the ending index
    Returns:
        the partition place of the arr
    '''
    import random
    # exchange arr[r] with a random place in the arr[p..r]≈
    i = random.randint(p, r)
    arr[r], arr[i] = arr[i], arr[r]
    return partition(arr, p, r)


def randomized_quicksort(arr, p, r):
    '''
    quicksort the arr with randomize method

    Parameters:
        arr - the array need to be sorted
        p - the beginning index
        r - the ending index
    Returns:
        none
    '''
    if p < r:
        q = randomized_partition(arr, p, r)
        randomized_quicksort(arr, p, q - 1)
        randomized_quicksort(arr, q + 1, r)
    

# test quicksort
arr = [1, 0, 2, 4, 4, 9, 9]
quicksort(arr, 0, len(arr) - 1)
print(arr)
# test quicksort_nonincreasing
quicksort_nonincreasing(arr, 0, len(arr) - 1)
print(arr)
# test randomized_quicksort
randomized_quicksort(arr, 0, len(arr) - 1)
print(arr)



# author Ttssxuan
# chapter 7.1
# the quicksort algorithm which consider that there are element identical

def partition_with_identical(arr, p, r):
    '''
    divide the arr[p..r] into two parts, the left less than arr[r], the right
    greater than the arr[r]

    Parameters:
        arr - the array need to be sorted
        p - the beginning index
        r - the ending index
    Returns:
        the partition place of the arr, q and t.
        all elements of arr[q..t] are equal
        each elements of arr[p..q - 1] is less than arr[q]
        each elements of arr[t + 1..r] is greater than arr[q]
    '''
    x = arr[r]
    i = p - 1
    t = p - 1
    # divide the arr
    for j in range(p, r):
        # exchange with arr[t + 1], for that arr[t + 1] >= x
        if arr[j] <= x:
            t += 1
            arr[t], arr[j] = arr[j], arr[t]
            # exchange with arr[i + 1], for that arr[i + 1] >= x
            if arr[t] < x:
                i += 1
                arr[i], arr[t] = arr[t], arr[i]
        
    # exchange the arr[r] to the right position
    arr[t + 1], arr[r] = arr[r], arr[t + 1]
    return i + 1, t + 1


def randomized_partition(arr, p, r):
    '''
    randomized the partition by exchange arr[r] with a random place

    Parameters:
        arr - the array need to be sorted
        p - the beginning index
        r - the ending index
    Returns:
        the partition place of the arr
    '''
    import random
    # exchange arr[r] with a random place in the arr[p..r]≈
    i = random.randint(p, r)
    arr[r], arr[i] = arr[i], arr[r]
    return partition_with_identical(arr, p, r)




def randomized_quicksort(arr, p, r):
    '''
    quicksort the arr with randomize method

    Parameters:
        arr - the array need to be sorted
        p - the beginning index
        r - the ending index
    Returns:
        none
    '''
    if p < r:
        q, t = randomized_partition(arr, p, r)
        randomized_quicksort(arr, p, q - 1)
        randomized_quicksort(arr, t + 1, r)
    

# test quicksort
arr = [1, 0, 2, 4, 4, 9, 9, 5, 5, 4, 10, 12, 13]
randomized_quicksort(arr, 0, len(arr) - 1)
print(arr)


# author Ttssxuan
# 7-1
# rewrite the quicksort with the hoare partition


def hoare_partition(arr, p, r):
    '''
    use the hoare method to patition the arr[p..r]

    Parameters:
        arr - the array need to be divide
        p - the beginning of the arr
        r - the ending of the arr
    Returns:
        the patition position of the array
    '''
    x = arr[p]
    i = p - 1
    j = r + 1
    while True:
        # find a element which less or equal x
        while True:
            j = j - 1
            if arr[j] <= x:
                break
        # find a element which greater of equal x
        while True:
            i = i + 1
            if arr[i] >= x:
                break
        # exchange the two
        if i < j:
            arr[i], arr[j] = arr[j], arr[i]
        else:
            return j

def quicksort(arr, p, r):
    '''
    quicksort the arr with the hoare method

    Parameters:
        arr - the array need to be sorted
        p - the beginning of the index
        r - the ending of the index
    Returns:
        the sorted array
    '''
    if p < r:
        # get the partition position
        q = hoare_partition(arr, p, r)
        # sort the first part
        quicksort(arr, p, q)
        # sort the second part
        quicksort(arr, q + 1, r)


# test
arr = [1, 8, 2, 10, 44, 0, 3, -1, 4]
quicksort(arr, 0, len(arr) - 1)
print(arr)
        


# author Ttssxuan
# chapter 7.1
# the quicksort algorithm which consider that there are element identical
# and use tail recursion to optimize the program

def partition_with_identical(arr, p, r):
    '''
    divide the arr[p..r] into two parts, the left less than arr[r], the right
    greater than the arr[r]

    Parameters:
        arr - the array need to be sorted
        p - the beginning index
        r - the ending index
    Returns:
        the partition place of the arr, q and t.
        all elements of arr[q..t] are equal
        each elements of arr[p..q - 1] is less than arr[q]
        each elements of arr[t + 1..r] is greater than arr[q]
    '''
    x = arr[r]
    i = p - 1
    t = p - 1
    # divide the arr
    for j in range(p, r):
        # exchange with arr[t + 1], for that arr[t + 1] >= x
        if arr[j] <= x:
            t += 1
            arr[t], arr[j] = arr[j], arr[t]
            # exchange with arr[i + 1], for that arr[i + 1] >= x
            if arr[t] < x:
                i += 1
                arr[i], arr[t] = arr[t], arr[i]
        
    # exchange the arr[r] to the right position
    arr[t + 1], arr[r] = arr[r], arr[t + 1]
    return i + 1, t + 1


def randomized_partition(arr, p, r):
    '''
    randomized the partition by exchange arr[r] with a random place

    Parameters:
        arr - the array need to be sorted
        p - the beginning index
        r - the ending index
    Returns:
        the partition place of the arr
    '''
    import random
    # exchange arr[r] with a random place in the arr[p..r]≈
    i = random.randint(p, r)
    arr[r], arr[i] = arr[i], arr[r]
    return partition_with_identical(arr, p, r)


def tail_recursive_quicksort(arr, p, r):
    '''
    quicksort the arr with randomize method

    Parameters:
        arr - the array need to be sorted
        p - the beginning index
        r - the ending index
    Returns:
        none
    '''
    while p < r:
        q, t = randomized_partition(arr, p, r)
        # make the shorter part recursive
        if (q - p) > (r - t):
            tail_recursive_quicksort(arr, t + 1, r)
            r = q - 1
        else:
            tail_recursive_quicksort(arr, p, q - 1)
            p = t + 1
    

# test quicksort
arr = [1, 0, 2, 4, 4, 9, 9, 5, 5, 4, 10, 12, 13]
tail_recursive_quicksort(arr, 0, len(arr) - 1)
print(arr)


# author Ttssxuan
# 7-6
# the fuzzy sorting of intervals

def partition(arr, p, r):
    '''
    divide the space into three parts, the smaller, the larger, and overlap with
    the main element

    Parameters:
        arr - the array need to be sort
        p - the beginning position
        r - the ending position
    Returns:
        the end of the smaller, and the beginning of the larger
    '''
    x = arr[r]
    q = p - 1
    t = r + 1
    j = p
    while j < r:
        # smaller than the main element, move it ahead
        if arr[j][1] < x[0]:
            q += 1
            arr[q], arr[j] = arr[j], arr[q]
        # larger than the main element, move if back
        elif arr[j][0] > x[1]:
            t -= 1
            arr[t], arr[j] = arr[j], arr[t]
            j -= 1
        j += 1
        if j == t:
            break

    return q + 1, t - 1


def fuzzysort(arr, p, r):
    '''
    sort the arr

    Parameters:
        arr - the arr need to be sorted
        p - the beginning of the array
        r - the ending of the array
    Returns:
        the sorted array
    '''
    if p < r:
        q, t = partition(arr, p, r)
        print(q, t)
        print(arr)
        fuzzysort(arr, p, q - 1)
        fuzzysort(arr, t + 1, r)


# test
arr = [[1, 2], [4, 5], [12, 14], [3, 6], [7, 9], [20, 24], [11, 13], [15, 17], [10, 11]]
fuzzysort(arr, 0, len(arr) - 1)
print(arr)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值