排序算法分析器(Python)

2018-07-18  本文已影响0人  import_hello

本文的最新版本位于:https://github.com/iwhales/algorithms_notes
转载请注明出处:https://www.jianshu.com/u/5e6f798c903a

本案例取自《数据结构(Python 语言描述)》- 3.7 案列学习:算法探查器。 作者提供的源代码中存在些许错误,本文修正了这些错误。

1. profiler 模块

Profiler 对象会跟踪指定算法的执行过程,统计比较次数和交换次数,并记录运行时间。另外,当算法交换某两个值时,分析器还可输出修改后的列表,以便观察列表的变化过程。

调用者可以向 Profiler 对象提供自定义的数值列表,或者让 Profiler 对象自动生成指定大小的随机排序数值列表。调用者还可以要求列表中是否允许包含重复元素。

"""
File: profiler.py

Defines a class for profiling sort algorithms.
A Profiler object tracks the list, the number of comparisons
and exchanges, and the running time. The Profiler can also
print a trace and can create a list of unique or duplicate
numbers.

Example use:

from profiler import Profiler
from algorithms import selectionSort

p = Profiler()
p.test(selectionSort, size = 15, comp = True,
             exch = True, trace = True)
"""

import time
import random

class Profiler(object):

    def test(self, function, lyst=None, size=10,
             unique=True, comp=True, exch=True,
             trace=False):
        """
        function: the algorithm being profiled
        target: the search target if profiling a search
        lyst: allows the caller to use her list
        size: the size of the list, 10 by default
        unique: if True, list contains unique integers
        comp: if True, count comparisons
        exch: if True, count exchanges
        trace: if True, print the list after each exchange

        Run the function with the given attributes and print
        its profile results.
        """
        self._comp = comp
        self._exch = exch
        self._trace = trace
        if lyst is not None:
            self._lyst = lyst
        elif unique:
            self._lyst = list(range(1, size + 1))
            random.shuffle(self._lyst)
        else:
            self._lyst = []
            for count in range(size):
                self._lyst.append(random.randint(1, size))
        self._exchCount = 0
        self._cmpCount = 0
        self._startClock()
        function(self._lyst, self)
        self._stopClock()
        print(self)

    def exchange(self):
        """Counts exchanges if on."""
        if self._exch:
            self._exchCount += 1
        if self._trace:
            print(self._lyst)

    def comparison(self):
        """Counts comparisons if on."""
        if self._comp:
            self._cmpCount += 1

    def _startClock(self):
        """Record the starting time."""
        self._start = time.time()

    def _stopClock(self):
        """Stops the clock and computes the elapsed time
        in seconds, to the nearest millisecond."""
        self._elapsedTime = round(time.time() - self._start, 3)

    def __str__(self):
        """Returns the results as a string."""
        result = "Problem size: "
        result += str(len(self._lyst)) + "\n"
        result += "Elapsed time: "
        result += str(self._elapsedTime) + "\n"
        if self._comp:
            result += "Comparisons:  "
            result += str(self._cmpCount) + "\n"
        if self._exch:
            result += "Exchanges:    "
            result += str(self._exchCount) + "\n"
        return result

2. algorithms 模块

该模块定义了几种排序函数。排序函数需要接受一个 Profiler 类型的参数,并在算法中涉及比较和交换的地方,调用 profiler.comparison()profiler.exchange() 。实际上任何处理列表的算法都可以利用类似的方法进行分析。

"""
File: algorithms.py
Algorithms configured for profiling.

"""

from profiler import Profiler

def selectionSort(lyst: list, profiler: Profiler):
    i = 0
    while i < len(lyst) - 1:         # Do n - 1 searches
        minIndex = i                 # for the largest
        j = i + 1
        while j < len(lyst):         # Start a search
            profiler.comparison()
            if lyst[j] < lyst[minIndex]:
                minIndex = j
            j += 1
        if minIndex != i:            # Exchange if needed
            swap(lyst, minIndex, i, profiler)
        i += 1

def bubbleSort(lyst, profiler):
    n = len(lyst)
    while n > 1:                       # Do n - 1 bubbles
        i = 1                          # Start each bubble
        while i < n:
            profiler.comparison()
            if lyst[i] < lyst[i - 1]:  # Exchange if needed
                swap(lyst, i, i - 1, profiler)
            i += 1
        n -= 1

def bubbleSort2(lyst, profiler):
    n = len(lyst)
    while n > 1:
        swapped = False
        i = 1
        while i < n:
            if lyst[i] < lyst[i - 1]:  # Exchange if needed
                swap(lyst, i, i - 1, profiler)
                swapped = True
            i += 1
            profiler.comparison()
        if not swapped:
            return
        n -= 1

def insertionSort(lyst, profiler):
    i = 1
    while i < len(lyst):
        itemToInsert = lyst[i]
        j = i - 1
        while j >= 0:
            profiler.comparison()
            if itemToInsert < lyst[j]:
                lyst[j + 1] = lyst[j]
                profiler.exchange()
                j -= 1
            else:
                break
        if j != i-1:
            lyst[j + 1] = itemToInsert
            profiler.exchange()
        i += 1

def swap(lyst, i, j, profiler):
    """Exchanges the elements at positions i and j."""
    profiler.exchange()
    temp = lyst[i]
    lyst[i] = lyst[j]
    lyst[j] = temp

3. testprofiler 模块

该模块用于执行测试:

from profiler import Profiler
from algorithms import selectionSort
import algorithms

p = Profiler()
p.test(selectionSort, size=15, comp=True,
       exch=True, trace=True)

p.test(algorithms.insertionSort, lyst=[1, 2, 3], trace=True)

输出展示:

[15, 1, 3, 5, 14, 9, 7, 11, 10, 13, 12, 4, 2, 6, 8]
[1, 15, 3, 5, 14, 9, 7, 11, 10, 13, 12, 4, 2, 6, 8]
[1, 2, 3, 5, 14, 9, 7, 11, 10, 13, 12, 4, 15, 6, 8]
[1, 2, 3, 4, 14, 9, 7, 11, 10, 13, 12, 5, 15, 6, 8]
[1, 2, 3, 4, 5, 9, 7, 11, 10, 13, 12, 14, 15, 6, 8]
[1, 2, 3, 4, 5, 6, 7, 11, 10, 13, 12, 14, 15, 9, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 10, 13, 12, 14, 15, 9, 11]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 13, 12, 14, 15, 10, 11]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 13, 11]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 13, 12]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 13, 14]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 14]
Problem size: 15
Elapsed time: 0.001
Comparisons:  105
Exchanges:    12

Problem size: 3
Elapsed time: 0.0
Comparisons:  2
Exchanges:    0
上一篇 下一篇

猜你喜欢

热点阅读