算法导论 python代码 第二章

# author Ttssxuan

# this is the sample of the selection sort

def selection_sort(arr):
    '''selection sort.
       arr: the arr you want to sort'''
    # find the ith element of the arr
    for i in range(0, len(arr) - 1):
        min = i
        # find the min element in rest
        for j in range(i + 1, len(arr)):
            if arr[j] < arr[min]:
                min = j
        #swap the ith element to the ith position
        temp = arr[min]
        arr[min] = arr[i]
        arr[i] = temp
#test
arr = [2, 4, 5, 9, 4]
selection_sort(arr)
print(str(arr))


# author Ttssxuan

# Insertion sort, sort the arr with ascent order

def insertion_sort(arr):
    '''Insertion_sort, arr: the input arr that we want to sort'''
    # scan every element of the arr and find the properly place for it
    for j in range(1, len(arr)):
        key = arr[j]
        i = j - 1
        # scan the sorted subarray arr[0..j -1], find the proper place
        while(i >= 0 and key < arr[i]):
            arr[i + 1] = arr[i]
            i = i - 1
        arr[i + 1] = key

# test
arr = [6, 2, 3, 4, 5]
insertion_sort(arr)
print(str(arr))


# author Ttssxuan
# Chapter 2

# merge sort, the provide two kinds of method to merge the two sequece.

from math import floor

def Merge(arr, p, q, e):
    '''The merge, arr:the array need to merge, p:the start place of the first
    part, q:the end of the first part, e:the end of the sencond merge part.
    This is the version of with sentinel.'''
    n1 = q - p + 1
    n2 = e - q
    l = [0] * (n1 + 1)
    r = [0] * (n2 + 1)
    # copy the first part from the initial arr
    for i in range(0, n1):
        l[i] = arr[p + i]
    # copy the second part from the initial arr
    for j in range(0, n2):
        r[j] = arr[q + j + 1]
    # set the sentinel of the two part
    l[n1] = 10000
    r[n2] = 10000
    i = 0
    j = 0
    # merge the two part to arr
    for k in range(p, e):
        if l[i] <= r[j]:
            arr[k] = l[i]
            i += 1
        else:
            arr[k] = r[j]
            j += 1

def Merge_no_sentinel(arr, p, q, e):
    '''The merge, arr:the array need to merge, p:the start place of the first
    part, q:the end of the first part, e:the end of the sencond merge part.
    This is the version of without sentinel'''
    n1 = q - p + 1
    n2 = e - q
    l = [0] * n1
    r = [0] * n2
    # copy the first part from the initail arr
    for i in range(0, n1):
        l[i] = arr[p + i]
    # copy the second pary from the initail arr
    for j in range(0, n2):
        r[j] = arr[q + j + 1]
        
    i = 0
    j = 0
    # merge the two part until one of the two part encount the end
    for k in range(p, e + 1):
        if (i < n1 and j < n2):
            if l[i] <= r[j]:
                arr[k] = l[i]
                i += 1
            else:
                arr[k] = r[j]
                j += 1
        else:
            break
    # copy the rest of the two part to the initail arr
    if i < n1:
        while k <= e:
            arr[k] = l[i]
            k += 1
            i += 1
    if j < n2:
        while k <= e:
            arr[k] = r[j]
            k += 1
            j += 1

def Merge_sort(arr, s, e):
    '''Use merge sort algorithm to sort the arr, and the start position is s,
    the end position is e.'''
    if s != e:
        # get the middle of the arr for s to e
        mid = int(floor((s + e) / 2))
        # merge sort the first part
        Merge_sort(arr, s, mid)
        # merge sort the second part
        Merge_sort(arr, mid + 1, e)
        # merge the tow part
        Merge_no_sentinel(arr, s, mid, e)

#test
arr = [1, 3, 5, 2, 4, 6]
Merge_sort(arr, 0, len(arr) - 1)
print(str(arr))

# author Ttssxuan
# 2.3-5
# binary search

import math

def binary_search(arr, value, s, e):
    '''arr:input, value:the value you wanted, s: start place in the arr, e:the
    end place in the arr
    if no such value RETURN -1, else RETURN the place of the value'''
    if s > e:
        return -1
    else:
        # get the middle of the index
        mid = int(math.floor((s + e) / 2))
        # judge the mid is equal the value
        if arr[mid] == value:
            return mid
        # search the first half
        elif arr[mid] > value:
            return binary_search(arr, value, s, mid - 1)
        # search the second half
        else:
            return binary_search(arr, value, mid + 1, e)

# test
arr = [1, 2, 3, 4, 5]
place = binary_search(arr, 1, 0, len(arr) - 1)
if place != -1:
    print("the place is ", place)
else:
    print("no such value")


# author Ttssxuan
# 2.3-7
# Describe a ‚.n lg n/-time algorithm that, given a set S of n integers
# and another integer x, determines whether or not there exist two
# elements in S whose sum is exactly x.

from math import floor
import math

def Merge_no_sentinel(arr, p, q, e):
    '''The merge, arr:the array need to merge, p:the start place of the first
    part, q:the end of the first part, e:the end of the sencond merge part.
    This is the version of without sentinel'''
    n1 = q - p + 1
    n2 = e - q
    l = [0] * n1
    r = [0] * n2
    # copy the first part from the initail arr
    for i in range(0, n1):
        l[i] = arr[p + i]
    # copy the second pary from the initail arr
    for j in range(0, n2):
        r[j] = arr[q + j + 1]
        
    i = 0
    j = 0
    # merge the two part until one of the two part encount the end
    for k in range(p, e + 1):
        if (i < n1 and j < n2):
            if l[i] <= r[j]:
                arr[k] = l[i]
                i += 1
            else:
                arr[k] = r[j]
                j += 1
        else:
            break
    # copy the rest of the two part to the initail arr
    if i < n1:
        while k <= e:
            arr[k] = l[i]
            k += 1
            i += 1
    if j < n2:
        while k <= e:
            arr[k] = r[j]
            k += 1
            j += 1

def Merge_sort(arr, s, e):
    '''Use merge sort algorithm to sort the arr, and the start position is s,
    the end position is e.'''
    if s != e:
        # get the middle of the arr for s to e
        mid = int(math.floor((s + e) / 2))
        # merge sort the first part
        Merge_sort(arr, s, mid)
        # merge sort the second part
        Merge_sort(arr, mid + 1, e)
        # merge the tow part
        Merge_no_sentinel(arr, s, mid, e)

def binary_search(arr, value, s, e):
    '''arr:input, value:the value you wanted, s: start place in the arr, e:the
    end place in the arr
    if no such value RETURN -1, else RETURN the place of the value'''
    if s > e:
        return -1
    else:
        mid = int(math.floor((s + e) / 2))
        if arr[mid] == value:
            return mid
        elif arr[mid] > value:
            return binary_search(arr, value, s, mid - 1)
        else:
            return binary_search(arr, value, mid + 1, e)


def estimate(arr, value):
    '''arr: the set which you want to search, value: the value you want to
        search.
        Return [first, second], if get the place, the first and second present
        the place of the two value, else return [-1, -1]'''
    # sort the array first
    Merge_sort(arr, 0, len(arr) - 1)
    # search each element of the arr
    for first in range(0, len(arr)):
        # calculate the other of the two
        rest = value - arr[first]
        # use binary search verify if there is the value
        second = binary_search(arr, rest, first + 1, len(arr) - 1)
        
        if second != -1:
            return [first, second]
    return [-1, -1]

# test 
arr = [1, 3, 4, 5]
print(arr)
result = estimate(arr, 10)
print(result)
result = estimate(arr, 4)
print(result)
result = estimate(arr, -1)
print(result)


# author Ttssxuan
# Problem 2-2
# bubblesort

def bubble_sort(arr):
    # total rearrange len(arr) times
    for i in range(0, len(arr) - 1):
        # swap the min of the arr[i, len(arr) - 1] to the top
        for j in range(len(arr) - 1, i, -1):
            if arr[j] < arr[j - 1]:
                # swap arr[j], arr[j - 1]
                arr[j], arr[j - 1] = arr[j - 1], arr[j]

# test
arr = [9, 2, 5, 2, 0, 2]
bubble_sort(arr)
print(arr)

# author Ttssxuan
# Problem 2-4 d

# Give an algorithm that determines the number of inversions in any permutation
# on n elements in ‚.n lg n/ worst-case time.
# We implement it by modifying merge sort

from math import floor

def Merge_no_sentinel(arr, p, q, e):
    '''The merge, arr:the array need to merge, p:the start place of the first
    part, q:the end of the first part, e:the end of the sencond merge part.
    This is the version of without sentinel
    return the inversion number of this merge'''
    n1 = q - p + 1
    n2 = e - q
    l = [0] * n1
    r = [0] * n2
    
    # copy the first part from the initail arr
    for i in range(0, n1):
        l[i] = arr[p + i]
    # copy the second pary from the initail arr
    for j in range(0, n2):
        r[j] = arr[q + j + 1]

    # recorder the total number of inversion
    inversion_number = 0
    # recorder the number of the numbers in array "r" which was added in "arr"
    count = 0
    i = 0
    j = 0
    # Merge the two part until one of the two part encount the end.
    # We know that if the number in ther array "l" less than the number in the
    # array "r", the pair of the number is not inversion, so we just count the
    # number in array "r" which added in the "arr" before the number in array
    # "l". Each this occur, we know there is inversion. 
    for k in range(p, e + 1):
        if (i < n1 and j < n2):
            if l[i] <= r[j]:
                arr[k] = l[i]
                i += 1
                # add the inversion for this number
                inversion_number += count
            else:
                arr[k] = r[j]
                j += 1
                # increase the number which was added in "arr"
                count += 1
        else:
            break
    # copy the rest of the two part to the initail arr
    if j < n2:
        while k <= e:
            arr[k] = r[j]
            k += 1
            j += 1
    if i < n1:
        while k <= e:
            arr[k] = l[i]
            k += 1
            i += 1
            # add the inversion for this number
            inversion_number += count
    return inversion_number
    

def Merge_sort(arr, s, e):
    '''Use merge sort algorithm to sort the arr, and the start position is s,
    the end position is e.
    return the inversion number of the arr'''
    inversion_number = 0
    if s != e:
        # get the middle of the arr for s to e
        mid = int(floor((s + e) / 2))
        # merge sort the first part
        inversion_number += Merge_sort(arr, s, mid)
        # merge sort the second part
        inversion_number += Merge_sort(arr, mid + 1, e)
        # merge the tow part
        inversion_number += Merge_no_sentinel(arr, s, mid, e)
    return inversion_number

def count_inversion(arr):
    '''count the inversion number of a sequence, which was implement by change
    the merge sort
    arr: the sequence we want to count
    return the inversion number of the sequence.'''
    return Merge_sort(arr, 0, len(arr) - 1)

#test
arr = [1, 2, 0, -1]
re = count_inversion(arr)
print re
arr = [0, 1, 2, 3]
re = count_inversion(arr)
print re
arr = [5, 4, 3, 2, 1]
re = count_inversion(arr)
print re


你可能感兴趣的:(算法)