算法导论 python代码 第八章

# author Ttssxuan
# chapter 8.1
# the counting sort

def counting_sort(arr, brr, k):
    '''
    use the counting sort algorithm to sorting arr place it in brr

    Parameters:
        arr - the array need to be sorted
        brr - the result sorted
        k - the max numbe of arr
    Returns:
        none
    '''
    c = [0] * (k + 1)
    # count the number of the element in arr equals i
    for j in range(0, len(arr)):
        c[arr[j]] = c[arr[j]] + 1
    # count the number of the element in arr less than or equals i
    for i in range(1, k + 1):
        c[i] = c[i] + c[i - 1]
    # find the appropriate place for arr[j]
    for j in range(len(arr) - 1, -1, -1):
        brr[c[arr[j]] - 1] = arr[j]
        # counting the next place for arr[j] if it exist again
        c[arr[j]] = c[arr[j]] - 1

# test
arr = [1, 2, 4, 9, 0, 10, 2, 4, 9, 6, 8]
brr = [0] * len(arr)
counting_sort(arr, brr, 10)
print(brr)


# 8.2-4
def preprocessing(arr, k):
    '''
    use the counting sort algorithm to count the number of the element in arr
    less than or equals to i

    Parameters:
        arr - the array need to be sorted
        k - the max numbe of arr
    Returns:
        the counting info
    '''
    c = [0] * (k + 1)
    # count the number of the element in arr equals i
    for j in range(0, len(arr)):
        c[arr[j]] = c[arr[j]] + 1
    # count the number of the element in arr less than or equals i
    print(c)
    for i in range(1, k + 1):
        c[i] = c[i] + c[i - 1]
    return c

def query(a, b, c):
    '''
    get the number of elements between a, b

    Parameters:
        a - the beginning of the scope
        b - the ending of the scope
        c - the counting info array
    Returns:
        the number of elements between a, b
    '''
    if a != 0:
        return c[b] - c[a - 1]
    else:
        return c[b]

# test
arr = [1, 2, 4, 9, 0, 10, 2, 4, 9, 6, 8]
c = preprocessing(arr, 10)
print(c)
print('1, 4', query(1, 4, c))
print('2, 9', query(2, 9, c))
print('3, 5', query(3, 5, c))


# author Ttssxuan
# chapter 8.1
# the radix sort

def counting_sort(arr, k, position):
    '''
    sort arr use count sort, at position whit k digite

    Parameters:
        arr - the array need to be sort
        k - the number of element
        position - the present position need to be sort
    '''
    c = [0] * k
    brr = [0] * len(arr)
    temp_arr  = [0] * len(arr)
    # get the position i number
    for i in range(0, len(arr)):
        temp_arr[i] = (arr[i] // 10 ** (position - 1)) % 10
    # get the count number
    for j in range(0, len(temp_arr)):
        c[temp_arr[j]] += 1
    for i in range(1, k):
        c[i] += c[i - 1]
    # sort arr
    for j in range(len(temp_arr) - 1, -1, -1):
        brr[c[temp_arr[j]] - 1] = arr[j]
        c[temp_arr[j]] = c[temp_arr[j]] - 1
    return brr

def radix_sort(arr, k, d):
    '''
    use radix sort algorithm sorting the arr

    Parameters:
        arr - the array need to be sort
        k - the possiblity of value
        d - the length of each digit
    '''
    # use counting sort algorithm sort every position
    for i in range(1, d + 1):
        arr = counting_sort(arr, k, i)
    return arr

# test
arr = [5556, 2023, 1239, 9875, 2491, 9931, 5955, 1035, 4025]
arr = radix_sort(arr, 10, 4)
print(arr)


# author Ttssxuan
# 8.3-1
# use the radix sort algorithm to sort some words

def counting_sort(arr, k, position):
    '''
    use counting sort algorithm sort the array, by its index position element

    Parameters:
        arr - the array need to be sort
        k - the vary number of the element
        position - the index of the array
    Returns:
        a sorted array by the index position of the array
    '''
    c = [0] * k
    brr = [0] * len(arr)
    # count the number of the arr[j][position] equals j
    for j in range(0, len(arr)):
        c[ord(arr[j][position]) - ord('A')] += 1
    # count the number of the arr[j][position] less than or equals j
    for i in range(1, k):
        c[i] += c[i - 1]
    # find the position for arr[j]
    for j in range(len(arr) - 1, -1, -1):
        brr[c[ord(arr[j][position]) - ord('A')] - 1] = arr[j]
        c[ord(arr[j][position]) - ord('A')] -= 1
    return brr

def radix_sort(arr, k, d):
    '''
    sort the arr, and the arr's element is string

    Parameters:
        arr - the array need to be sorted
        k - the vary value of the element
        d - the len of the element
    '''
    for i in range(d - 1, -1, -1):
        arr = counting_sort(arr, k, i)
    return arr

# test
arr = ['COW', 'DOG', 'SEA', 'RUG', 'ROW', 'MOB', 'BOX', 'TAB', 'BAR', 'EAR',
       'TAR', 'DIG', 'BIG', 'TEA', 'NOW', 'FOX']
arr = radix_sort(arr, 26, 3)
print(arr)


# author Ttssxuan
# chapter 8.4
# the bucket sort

from math import floor

def insert_sort(arr):
    '''
    use insert sort algorithm to sort the arr

    Parameters:
        arr - the array need to be sorted
    Returns:
        none
    '''
    for i in range(1, len(arr)):
        x = arr[i]
        j = i - 1
        while j >= 0 and x < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = x
        

def bucket_sort(arr):
    '''
    use the backet sort algorithm to sort the arr

    Parameters:
        arr - the array need to be sorted
    Returns:
        the sorted arr
    '''
    # get the length
    n = len(arr)
    # make the backet
    brr = [[] for i in range(0, n)]
    # distribute the elements in arr to the backets
    for i in range(0, n):
        brr[int(floor(n * arr[i]))].append(arr[i])
    # sort the elements in each backet
    for i in range(0, n):
        insert_sort(brr[i])
        # concatenate the array
        if i != 0:
            brr[0] += brr[i]
    return brr[0]
    

# test
arr = [0.1, 0.01, 0.5, 0.4, 0.22, 0.98, 0.34, 0.33]
brr = bucket_sort(arr)
print(brr)


# author Ttssxuan
# 8-3
# sorting variable-lenth items


# 8-3 a
def counting_sort(arr, k, position):
    '''
    sort arr use count sort, at position whit k digite

    Parameters:
        arr - the array need to be sort
        k - the number of element
        position - the present position need to be sort
    '''
    c = [0] * k
    brr = [0] * len(arr)
    temp_arr  = [0] * len(arr)
    # get the position i number
    for i in range(0, len(arr)):
        temp_arr[i] = (arr[i] // 10 ** (position - 1)) % 10
    # get the count number
    for j in range(0, len(temp_arr)):
        c[temp_arr[j]] += 1
    for i in range(1, k):
        c[i] += c[i - 1]
    # sort arr
    for j in range(len(temp_arr) - 1, -1, -1):
        brr[c[temp_arr[j]] - 1] = arr[j]
        c[temp_arr[j]] = c[temp_arr[j]] - 1
    return brr

def radix_sort(arr, k, d):
    '''
    use radix sort algorithm sorting the arr

    Parameters:
        arr - the array need to be sort
        k - the possiblity of value
        d - the length of each digit
    '''
    # use counting sort algorithm sort every position
    if len(arr) == 0:
        return []
    for i in range(1, d + 1):
        arr = counting_sort(arr, k, i)
    return arr

def sort_n_width_number(arr, n):
    '''
    sort an array of number whose total digits number equals n, in O(n)

    Parameters:
        arr - the array need to be sort
        n - the total number of digits
    '''
    # use the counting sort divide the arr into groups and the elements in
    # each group has the same number of digits
    c = [0] * (n + 1)
    place = [0] * (n + 1)
    brr = [0] * len(arr)
    for i in range(0, len(arr)):
        c[len(str(arr[i]))] += 1
    for i in range(1, n + 1):
        c[i] += c[i - 1]
    for i in range(0, n + 1):
        place[i] = c[i]
    # divide into groups
    for j in range(len(arr) - 1, -1, -1):
        brr[c[len(str(arr[j]))] - 1] = arr[j]
        c[len(str(arr[j]))] -= 1
    # use radix sort algorithm sorting each group
    for i in range(1, n + 1):
        brr[place[i - 1]:place[i]] = radix_sort(brr[place[i - 1]:place[i]], 10, i)
    return brr

# test sort_n_width_number
arr = [1, 3, 22, 44, 34, 42, 6, 334, 223, 555]
brr = sort_n_width_number(arr, 20)
print(brr)
arr = [13, 5, 333, 22, 2, 59, 0, 44, 34, 42, 6, 334, 223, 555]
brr = sort_n_width_number(arr, 28)
print(brr)


# 8-3 b
def sort_n_width_string(arr, n):
    '''
    sort the arr with total n characters by a lexicographically with O(n) time

    Parameters:
        arr - the array needs to be sorted
        n - the total number of characters in the array
    Returns:
        the sorted arr
    '''
    c = [0] * 53
    place = [0] * 53
    brr = [0] * len(arr)
    # there is no need to calculating
    if len(arr) == 0:
        return arr
    # count the number of strings which beginning with conrespond letter
    for i in range(0, len(arr)):
        if len(arr[i]) <= n:
            c[0] += 1
        elif ord(arr[i][n]) >= 97:
            c[27 + ord(arr[i][n]) - 97] += 1
        else:
            c[1 + ord(arr[i][n]) - 65] += 1
    # there are only empty strings, no need to calculating
    if c[0] == len(arr):
        return arr
    # counting the number of strings less than current string
    for i in range(1, 53):
        c[i] += c[i - 1]
        place[i] = c[i]
    # find the appropriate place for the string
    for i in range(len(arr) - 1, -1, -1):
        if len(arr[i]) <= n:
            brr[c[0] - 1] = arr[i]
            c[0] -= 1
        elif ord(arr[i][n]) >= 97:
            brr[c[27 + ord(arr[i][n]) - 97] - 1] = arr[i]
            c[27 + ord(arr[i][n]) - 97] -= 1
        else:
            brr[c[1 + ord(arr[i][n]) - 65] - 1] = arr[i]
            c[1 + ord(arr[i][n]) - 65] -= 1
    # recurrence sort the subarray
    for i in range(1, 53):
        brr[place[i - 1]:place[i]] = sort_n_width_string(brr[place[i - 1]:place[i]], n + 1)

    return brr

# test sort_n_width_string
arr = ['aa', 'b', '', 'c', 'addb', 'calkd', 'bd', 'ab', 'abcd', 'sssa']
brr = sort_n_width_string(arr, 0)
print(brr)
arr = ['aa', 'b', 'C', 'A', 'B', 'CDE', 'DDSE', '', 'c', 'addb', 'calkd', 'bd', 'ab', 'abcd', 'sssa']
brr = sort_n_width_string(arr, 0)
print(brr)


# author Ttssxuan
# 8-4
# the water jugs problem

import random

# define the jug class
class jug:
    def __init__(self, pos, volume):
        self.pos = pos
        self.volume = volume

def split(arr, key, p, r):
    '''
    split the arr[p..r] into two part, arr[p..i] < key, arr[i + 1..r] >= key

    Parameters:
        arr - the arr need to be splited
        key - the pivot
        p - the start index of the arr
        r - the end index of the arr
    Returns:
        the split point
    '''
    i = p - 1
    # split the array
    for j in range(p, r + 1):
        if arr[j].volume < key:
            i += 1
            arr[i], arr[j] = arr[j], arr[i]
    return i

def match_jugs(rrr, rs, re, brr, bs, be):
    '''
    solve the match jugs problem as the quicksort, and output the pair

    Parameters:
        rrr - the red jugs
        rs - the beginning of the red jugs
        re - the ending of the blue jugs
        brr - the blue jugs
        bs - the beginning of the blue jugs
        be - the ending of the blue jugs
    Returns:
        none
    '''
    if rs > re:
        return
    if rs == re:
        print("pair red:", rrr[rs].pos, "blue:", brr[bs].pos)
        return
    else:
        ra = random.randint(rs, re)
        rrr[ra], rrr[re] = rrr[re], rrr[ra]
        split_r = split(rrr, rrr[re].volume, rs, re)
        split_b = split(brr, rrr[re].volume, bs, be)
        match_jugs(rrr, rs, split_r, brr, bs, split_b)
        match_jugs(rrr, split_r + 1, re, brr, split_b + 1, be)
        

# test match_jugs
print("test 1")
rrr = [jug(0, 4), jug(1, 2), jug(2, 6), jug(3, 11), jug(4, 23), jug(5, 10)]
brr = [jug(0, 6), jug(1, 2), jug(2, 4), jug(3, 23), jug(4, 10), jug(5, 11)]
match_jugs(rrr, 0, len(rrr) - 1, brr, 0, len(brr) - 1)
print("test 2")
rrr = [jug(0, 4)]
brr = [jug(0, 4)]
match_jugs(rrr, 0, len(rrr) - 1, brr, 0, len(brr) - 1)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值