数据结构之算法

1.算法性能评估

1.度量算法的运行时间

使用计算机的时钟来获取一个实际的运行时间

2.统计指令

统计对不同的问题规模索要执行的指令的数目
1.不管问题规模多大,都执行相同的次数的指令
2.根据问题的规模,执行不同次数的指令

# 循环中
problemSize = 1000
print("%12s%15s" % ("problem size", "Iterations"))
for count in range(5):
    number = 0
    # The start of the algorithm
    work = 1
    for j in range(problemSize):
        for k in range(problemSize):
            number += 1
            work += 1
            work -= 1
    # the end of the algorithm
    print("%12d%15d" % (problemSize, number))
    problemSize *= 2
运行结果:
	problem size     Iterations
        1000        1000000
        2000        4000000
        4000       16000000
        8000       64000000
       16000      256000000
# 递归
# counter类见上一章
from counter import Counter

def fib(n, counter):
	"""计算调用斐波那契函数的次数"""
	counter.increment()
	if n < 3:
		return 1
	else:
		return fib(n-1, counter) + fib(n-2, counter)

problemSize = 2
print("%12s%15s % ('Problem Size', 'Calls'))
for count in range(5):
	counter = Counter()
	fib(problemSize, counter)
	print("%12d%15s" % (problemSize, counter))
	problemSize *=2
Problem Size	  Calls
       2			1
       4			5
       8			41
      16			1973
      32        	4356617

3.度量算法使用的内存

2.复杂度分析

2.1复杂度的阶

O表示,一个线性时间算法的阶是O(n)

2.2最坏时间复杂度

  • 算法完成工作最少需要多少基本操作,最优时间复杂度
  • 算法完成工作最多需要多少基本操作,最坏时间复杂度
  • 算法完成工作平均需要多少基本操作,平均时间复杂度

2.3时间复杂度的基本计算规则

1.基本操作,即只有常数项,认为其时间复杂度为O(1)
2.顺序结构,时间复杂度按加法进行计算
3.循环结构,时间复杂度按乘法进行计算
4.分支结构,时间复杂度取最大值
5.判断算法效率,关注操作数量的最高次项,其他次要项和常数项可以忽略
6.没有特殊说明,分析的算法的时间复杂度都是指最坏时间复杂度

3.搜索算法

3.1 搜索最小值

复杂度是O(n)

lst = [1, 4, 5, 3, 2, 0, 6, 7]
def indexOfMin(lyst):
	"""Returns the index of the minimum item"""
	minIndex = 0
	currentIndex = 1
	while currentIndex < len(lyst):
		if lyst[currentIndex] < lyst[minIndex]:
			minIndex = currentIndex
		currentIndex += 1
	return minIndex

print(indexOfMin(lst))		# 返回列表最小值的索引
print(lst[indexOfMin(lst)])	# 打印最小值
5
0

3.2顺序搜索一个无序列表

复杂度是O(n)

lst = [1, 4, 5, 3, 2, 0, 6, 7]

def sequentialSearch(target, lyst):
    """Returns the postion of the target item if found,or -1 otherwise"""
    position = 0
    while position < len(lyst):
        if target == lyst[position]:
            return position
        position += 1
    return -1

print(sequentialSearch(5, lst))		# 打印目标值在列表中的索引位置
2

3.3有序列表的二分法搜索

复杂度O(log₂N)

lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def binarySearch(target, sortedLyst):
    left = 0
    right = len(sortedLyst) -1 
    while left <= right:
        midpoint = (left + right) // 2
        if target == sortedLyst[midpoint]:
            return midpoint
        elif target < sortedLyst[midpoint]:
            right = midpoint - 1
        else:
            left = midpoint + 1
    return -1

print(binarySearch(5, lst))		# 打印目标值列表索引
4

3.4比较数据项

class SavingsAccount(object):
    def __init__(self, name, PIN, balance = 0.0):
        self._name = name
        self._PIN = PIN
        self._balance = balance

    def __lt__(self, other):
        return self._name < other._name

    def __eq__(self, other):
        return self._name == other._name
        
s1 = SavingsAccount("Knight", "1000", "0")
s2 = SavingsAccount("Queen", "1001", "30")
s3 = SavingsAccount("Knight", "1000", "0")
print(s2 < s1)
print(s3 == s1)
False
True

4.基本排序算法

基本的排序算法都用的函数

lst = [1, 3, 2, 4]

def swap(lyst, i, j):
    """Exchange the items at position i and j"""
    # lyst[i], lyst[j] = lyst[j], lyst[i]
    temp = lyst[i]
    lyst[i] = lyst[j]
    lyst[j] = temp

swap(lst, 1, 2)
print(lst)
[1, 2, 3, 4]

4.1选择排序

复杂度O(n²)

# swap方法见上面
lst = [5, 3, 2, 1, 4]

def selectionSort(lyst):
    i = 0
    while i < len(lyst) - 1:
        minIndex = i
        j = i + 1
        while j < len(lyst):
            if lyst[j] < lyst[minIndex]:
                minIndex = j
            j += 1
        if minIndex != i:
            swap(lyst, minIndex, i)
        i += 1

selectionSort(lst)
print(lst)
[1, 2, 3, 4, 5]

4.2冒泡排序

复杂度O(n²)

lst = [5, 3, 2, 1, 4]

def bubbleSort(lyst):
    n = len(lyst)
    while n > 1:
        i = 1
        while i < n:
            if lyst[i] < lyst[i-1]:
                swap(lyst, i, i-1)
            i += 1
        n -= 1

bubbleSort(lst)
print(lst)
[1, 2, 3, 4, 5]

4.3插入排序

复杂度O(n²)

lst = [5, 3, 2, 1, 4]
def insertionSort(lyst):
    i = 1
    while i < len(lyst):
        itemToInsert = lyst[i]
        j = i - 1
        while j >= 0:
            if itemToInsert < lyst[j]:
                lyst[j + 1] = lyst[j]
                j -= 1
            else:
                break
        lyst[j + 1] = itemToInsert
        i += 1
insertionSort(lst)
print(lst)
[1, 2, 3, 4, 5]

5.更快排序

5.1快速排序

复杂度O(n²)

import random

def swap(lyst, i, j):
    """Exchange the items at position i and j"""
    # lyst[i], lyst[j] = lyst[j], lyst[i]
    temp = lyst[i]
    lyst[i] = lyst[j]
    lyst[j] = temp

def quicksort(lyst):
    quicksortHelper(lyst, 0, len(lyst) - 1)

def quicksortHelper(lyst, left, right):
    if left < right:
        pivotLocation = partition(lyst, left, right)
        quicksortHelper(lyst, left, pivotLocation - 1)
        quicksortHelper(lyst, pivotLocation + 1, right)

def partition(lyst, left, right):
    # Find the pivot and exchange it with the last item
    middle = (left + right) // 2
    pivot = lyst[middle]
    lyst[middle] = lyst[right]
    lyst[right] = pivot
    # Set boundarypoint to first position
    boundary = left
    # Move items less than pivot to the left
    for index in range(left, right):
        if lyst[index] < pivot:
            swap(lyst, index, boundary)
            boundary += 1
    # Exchange definition of the swap function goes here
    swap(lyst, right, boundary)
    return boundary

def main(size=20, sort=quicksort):
    lyst = []
    for count in range(size):
        lyst.append(random.randint(1, size + 1))
    sort(lyst)
    print(lyst)

if __name__ == "__main__":
    main()
随机列表快速排序

5.2合并排序

复杂度O(nlogn)

class Array(object):
    def __init__(self, capacity, fileValue=None):
        """
        :param capacity: 数组容量的大小
        :param fileValue: 数组每个位置的值
        """
        self._items = list()
        for count in range(capacity):
            self._items.append(fileValue)

    def __len__(self):
        """
        数组容量的大小
        """
        return len(self._items)

    def __str__(self):
        """
        数组的字符串表示形式
        """
        return str(self._items)

    def __iter__(self):
        """
        支持遍历for循环
        """
        return iter(self._items)

    def __getitem__(self, index):
        """
        用于索引访问的下标运算符
        """
        return self._items[index]

    def __setitem__(self, index, newItem):
        """
        在索引处替换的下标运算符
        """
        self._items[index] = newItem

def mergeSort(lyst):
    """
    :param lyst: # 列表排序
    """
    copyBuffer = Array(len(lyst))   # 合并期间需要的临时空间
    mergeSortHelper(lyst, copyBuffer, 0, len(lyst) - 1)

def mergeSortHelper(lyst, copyBuffer, low, high):
    """
    :param lyst:    # 列表排序
    :param copyBuffer: # 合并期间需要的临时空间
    :param low, high:  # 子表的边界
    :param middle:  # 子表的中间
    """
    if low < high:
        middle = (low + high) // 2
        mergeSortHelper(lyst, copyBuffer, low, middle)
        mergeSortHelper(lyst, copyBuffer, middle + 1, high)
        merge(lyst, copyBuffer, low, middle, high)

def merge(lyst, copyBuffer, low, middle, high):
    """
    :param lyst: # 正在排序的列表
    :param copyBuffer: # 合并过程中需要的临时空间
    :param low: # 第一个排序子列表的开头
    :param middle: # 第一个排序子列表的结尾
    :param middle + 1: # 第二个排序子列表的开头
    :param high: # 第二个排序子列表的结尾
    """
    i1 = low
    i2 = middle + 1
    for i in range(low, high + 1):
        if i1 > middle:
            copyBuffer[i] = lyst[i2]    # 第一个子列表用尽了
            i2 += 1
        elif i2 > high:
            copyBuffer[i] = lyst[i1]    # 第二个子列表用尽了
            i1 += 1
        elif lyst[i1] < lyst[i2]:
            copyBuffer[i] = lyst[i1]    # 第一个子列表中的项目
            i1 += 1
        else:
            copyBuffer[i] = lyst[i2]    # 第二个子列表中的项目
            i2 += 1

    for i in range(low, high + 1):      # 将已排序的项目复制回列表中的正确位置
        lyst[i] = copyBuffer[i]

lst = [4, 1, 7, 6, 5, 3, 8, 2]

mergeSort(lst)
print(lst)
[1, 2, 3, 4, 5, 6, 7, 8]

6.Fibonacci算法

6.1Fibonacci指数算法

复杂度O(K^n) ==> k = 1.63

def  fib(n):
	# 斐波那契函数的递归
	if n < 3:
		return 1
	else:
		return fib(n -1) + fib(n -2)

6.2Fibonacci线性算法

复杂度O(n)

class Counter(object):
    """Models a counter。"""

    # Class variable
    instance = 0

    # Constructor
    def __init__(self):
        """Sets up the counter"""
        Counter.instance += 1
        self.reset()        # 初始化对象,

    # Mutator methods   # 修改器
    def reset(self):
        """Sets the Counter to 0"""
        self._value = 0

    def increment(self, amount=1):
        """Adds amount to the counter"""
        self._value += amount

    def decrement(self, amount=1):
        """Subtracts amount from the counter"""
        self._value -= amount

    # Accessor methods  # 访问器
    def getValue(self):
        """Returns The counter`s values"""
        return self._value

    def __str__(self):
        """Returns the string representation of the counter"""
        return  str(self._value)

    def __eq__(self, other):
        """Returns True if self equals other or False otherwise"""
        if self is other:
            return True
        if type(self) != type(other):
            return False
        return self._value == other._value

problemSize = 2

def fib(n, counter):
    # 计算斐波那契函数的迭代次数
    sum = 1
    first = 1
    second = 1
    count = 3
    while count <= n:
        counter.increment()
        sum = first + second
        first = second
        second = sum
        count += 1

    return sum

print("%12s%15s" % ('Problem Size', 'Iterations'))
for count in range(5):
    counter = Counter()
    fib(problemSize, counter)
    print("%12d%15s" % (problemSize, counter))
    problemSize *= 2
Problem Size          Iterations
       2              		0
       4              		2
       8              		6
      16             		14
      32             		30
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值