| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- # Natural Language Toolkit: List Sorting
- #
- # Copyright (C) 2001-2020 NLTK Project
- # Author: Steven Bird <stevenbird1@gmail.com>
- # URL: <http://nltk.org/>
- # For license information, see LICENSE.TXT
- """
- This module provides a variety of list sorting algorithms, to
- illustrate the many different algorithms (recipes) for solving a
- problem, and how to analyze algorithms experimentally.
- """
- # These algorithms are taken from:
- # Levitin (2004) The Design and Analysis of Algorithms
- ##################################################################
- # Selection Sort
- ##################################################################
- def selection(a):
- """
- Selection Sort: scan the list to find its smallest element, then
- swap it with the first element. The remainder of the list is one
- element smaller; apply the same method to this list, and so on.
- """
- count = 0
- for i in range(len(a) - 1):
- min = i
- for j in range(i + 1, len(a)):
- if a[j] < a[min]:
- min = j
- count += 1
- a[min], a[i] = a[i], a[min]
- return count
- ##################################################################
- # Bubble Sort
- ##################################################################
- def bubble(a):
- """
- Bubble Sort: compare adjacent elements of the list left-to-right,
- and swap them if they are out of order. After one pass through
- the list swapping adjacent items, the largest item will be in
- the rightmost position. The remainder is one element smaller;
- apply the same method to this list, and so on.
- """
- count = 0
- for i in range(len(a) - 1):
- for j in range(len(a) - i - 1):
- if a[j + 1] < a[j]:
- a[j], a[j + 1] = a[j + 1], a[j]
- count += 1
- return count
- ##################################################################
- # Merge Sort
- ##################################################################
- def _merge_lists(b, c):
- count = 0
- i = j = 0
- a = []
- while i < len(b) and j < len(c):
- count += 1
- if b[i] <= c[j]:
- a.append(b[i])
- i += 1
- else:
- a.append(c[j])
- j += 1
- if i == len(b):
- a += c[j:]
- else:
- a += b[i:]
- return a, count
- def merge(a):
- """
- Merge Sort: split the list in half, and sort each half, then
- combine the sorted halves.
- """
- count = 0
- if len(a) > 1:
- midpoint = len(a) // 2
- b = a[:midpoint]
- c = a[midpoint:]
- count_b = merge(b)
- count_c = merge(c)
- result, count_a = _merge_lists(b, c)
- a[:] = result # copy the result back into a.
- count = count_a + count_b + count_c
- return count
- ##################################################################
- # Quick Sort
- ##################################################################
- def _partition(a, l, r):
- p = a[l]
- i = l
- j = r + 1
- count = 0
- while True:
- while i < r:
- i += 1
- if a[i] >= p:
- break
- while j > l:
- j -= 1
- if j < l or a[j] <= p:
- break
- a[i], a[j] = a[j], a[i] # swap
- count += 1
- if i >= j:
- break
- a[i], a[j] = a[j], a[i] # undo last swap
- a[l], a[j] = a[j], a[l]
- return j, count
- def _quick(a, l, r):
- count = 0
- if l < r:
- s, count = _partition(a, l, r)
- count += _quick(a, l, s - 1)
- count += _quick(a, s + 1, r)
- return count
- def quick(a):
- return _quick(a, 0, len(a) - 1)
- ##################################################################
- # Demonstration
- ##################################################################
- def demo():
- from random import shuffle
- for size in (10, 20, 50, 100, 200, 500, 1000):
- a = list(range(size))
- # various sort methods
- shuffle(a)
- count_selection = selection(a)
- shuffle(a)
- count_bubble = bubble(a)
- shuffle(a)
- count_merge = merge(a)
- shuffle(a)
- count_quick = quick(a)
- print(
- (
- ("size=%5d: selection=%8d, bubble=%8d, " "merge=%6d, quick=%6d")
- % (size, count_selection, count_bubble, count_merge, count_quick)
- )
- )
- if __name__ == "__main__":
- demo()
|