mit 6.006 recitation-003

90 阅读2分钟

A fast set: sorted array:

class Sorted_Array_Set:
    def __init__(self):
        self.A = Array_Seq()

    def __len__(self):
        return len(self.A)

    def __iter__(self):
        yield from self.A

    def iter_order(self):
        yield from self

    def build(self, X):
        self.build()
        self.sort()

    # def sort(self):

    def _binary_sort(self, k, i, j):
        if i >= j: return i
        m = (i + j) // 2
        x = self.A.get_at(m)
        if x.key > k: self._binary_sort(k, i, m - 1)
        if x.key < k: self._binary_sort(k, m + 1, j)
        return m

    def find_min(self):
        if len(self.A) > 0: return self.A.get_at(0)

    def find_max(self):
        if len(self.A) > 0: return self.A.get_at(len(self) - 1)

    def find(self, k):
        if len(A) == 0: return None
        i = self._binary_sort(k, 0, len(self) - 1)
        x = self.A.get_at(i)
        if x.key == k:
            return x
        else:
            return None

    def find_next(self, k):
        if len(self) == 0: return None
        i = self._binary_sort(A, 0, len(self) - 1)
        x = self.A.get_at(i)
        if x.key > k: return x
        if i + 1 < len:
            return self.A.get_at(i + 1)
        else:
            return None

    def find_pref(self, k):
        if len(self) == 0: return None
        i = self._binary_sort(A, 0, len(A) - 1)
        x = self.A.get_at(i)
        if x.key < k: return x
        if i > 0:
            return self.A.get_at(i - 1)
        else:
            return None

    def delete(self, k):
        i = self._binary_sort(l, 0, len(self.A) - 1)
        assert self.get_at(i).key == k
        return self.delete_at(i)

In this data structure, we can find the item easility by the binary research for lognlog n time.

Selection Sort:

pattern 1

def selection_sort(A):
    for i in range(len(A) - 1, 0, -1):
        max = i
        for j in range(i):
                max = A[j]
        A[max], A[i] = A[i], A[max]

pattern 2:

def selection_sort(A, i=None):
    if i is None:
        i = len(A) - 1
    if i > 0:
        j = prefix_max(A, i)
        A[i], A[j] = A[j], A[i]
        selection_sort(A, i - 1)


def prefix_max(A, i):
    if i > 0:
        j = prefix_max(A, i - 1)
        if A[j] > A[i]:
            return j
    return i

Insertion_sort

def insertion_sort(A):
    for i in range(1, len(A)):
        j = i
        while j > 0 and A[j] < A[j - 1]:
            A[j], A[j - 1] = A[j - 1], A[j]
            j = j - 1

Selection and Insertion Sort:

the same:

  • Both are incremental in that they maintain, and grow a sorted subset until all the items are sorted.
  • Both are in-place algorithms,using a constant space , don't need a more space

Differences:

  • Selection sort:
    • maintain the largest items
  • Insertion sort:
    • maintain the first i input

Insertion Sort is more stable,the output will be the same from the same input.

Merge_sort

def merge_sort(A, a=0, b=None):
    if b == None: b = len(A)
    if b - a > 1:
        c = (a + b + 1) // 2
        merge_sort(A, a, c)
        merge_sort(A, c, b)
        L, R = A[a:c], A[c:b]
        i, j = 0, 0
        while a < b:
            if (j >= len(R)) or (i < len(L) and L[i] < R[j]):
                A[a] = L[i]
                i = i + 1
            else:
                A[a] = R[j]
                j = j + 1
            a = a + 1

We need a temporary space to combine the two halves.It's not in-space algorithm.

Build a sorted array:

sacrifice some time in building the data structure to speed up our order queries,which is called preprocessing.