数据结构之算法

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
12篇学通csharp网络编程——第四篇 TCP应用编程 12篇学通csharp网络编程——第三篇 HTTP应用编程(下) 12篇学通csharp网络编程——第二篇 HTTP应用编程(上) 12篇学通csharp网络编程——第一篇 基础之进程线程 Lucene(1)lucene,你也会(7篇)——第一篇 快速入门 MongoDB(8)8天学通MongoDB——第八天 驱动实践 8天学通MongoDB——第七天 运维技术 8天学通MongoDB——第六天 分片技术 8天学通MongoDB——第五天 主从复制 8天学通MongoDB——第四天 索引操作 8天学通MongoDB——第三天 细说高级操作 8天学通MongoDB——第二天 细说增删查改 8天学通MongoDB——第一天 基础入门 UML系列(4)团队沟通利器之UML——类图 团队沟通利器之UML—— 序列图 团队沟通利器之UML——用例图 团队沟通利器之UML——活动图 wcf系列(5)wcf系列学习5天速成——第五天 服务托管 wcf系列学习5天速成——第四天 wcf之分布式架构 wcf系列学习5天速成——第三天 事务的使用 wcf系列5天速成——第二天 binding的使用(2) wcf系列5天速成——第一天 binding的使用(1) wpf系列(8)8天入门wpf—— 第八天 最后的补充 8天入门wpf—— 第七天 画刷 8天入门wpf—— 第六天 细说控件 8天入门wpf—— 第五天 数据绑定 8天入门wpf—— 第四天 模板 8天入门wpf—— 第三天 样式 8天入门wpf—— 第二天 xaml详解 8天入门wpf—— 第一天 基础概念介绍 并行开发(8)8天玩转并行开发——第八天 用VS性能向导解剖你的程序 8天玩转并行开发——第七天 简要分析任务与线程池 8天玩转并行开发——第六天 异步编程模型 8天玩转并行开发——第五天 同步机制(下) 8天玩转并行开发——第四天 同步机制(上) 8天玩转并行开发——第三天 plinq的使用 8天玩转并行开发——第二天 Task的使用 8天玩转并行开发——第一天 Parallel的使用 多线程系列(5)5天不再惧怕多线程——第五天 线程池 5天不再惧怕多线程——第四天 信号量 5天不再惧怕多线程——第三天 互斥体 5天不再惧怕多线程——第二天 锁机制 5天不再惧怕多线程——第一天 尝试Thread 经典算法专题(21)经典算法题每日演练——第二十一题 十字链表 经典算法题每日演练——第二十题 三元组 经典算法题每日演练——第十九题 双端队列 经典算法题每日演练——第十八题 外排序 经典算法题每日演练——第十七题 Dijkstra算法 经典算法题每日演练——第十六题 Kruskal算法 经典算法题每日演练——第十五题 并查集 经典算法题每日演练——第十四题 Prim算法 经典算法题每日演练——第十三题 赫夫曼树 经典算法题每日演练——第十二题 线段树 经典算法题每日演练——第十一题 Bitmap算法 经典算法题每日演练——第十题 树状数组 经典算法题每日演练——第九题 优先队列 经典算法题每日演练——第八题 AC自动机 经典算法题每日演练——第七题 KMP算法 经典算法题每日演练——第六题 协同推荐SlopeOne 算法 经典算法题每日演练——第五题 字符串相似度 经典算法题每日演练——第四题 最长公共子序列 经典算法题每日演练——第三题 猴子吃桃 经典算法题每日演练——第二题 五家共井 经典算法题每日演练——第一题 百钱买百鸡 开发利器系列(1)介绍一个小工具 Linqer 那点所谓的分布式(2)那点所谓的分布式——memcache 那点所谓的分布式——redis 树结构专题(5)6天通吃树结构—— 第五天 Trie树 6天通吃树结构—— 第四天 伸展树 6天通吃树结构—— 第三天 Treap树 6天通吃树结构—— 第二天 平衡二叉树 6天通吃树结构—— 第一天 二叉查找树 算法速成系列(15)算法系列15天速成——第十五天 图【下】(大结局) 算法系列15天速成——第十四天 图【上】 算法系列15天速成——第十三天 树操作【下】 算法系列15天速成——第十二天 树操作【中】 算法系列15天速成——第十一天 树操作(上) 算法系列15天速成——第十天 栈 算法系列15天速成——第九天 队列 算法系列15天速成——第八天 线性表【下】 算法系列15天速成——第七天 线性表【上】 算法系列15天速成——第六天 五大经典查找【下】 算法系列15天速成——第五天 五大经典查找【中】 算法系列15天速成——第四天 五大经典查找【上】 算法系列15天速成——第三天 七大经典排序【下】 算法系列15天速成——第二天 七大经典排序【中】 算法系列15天速成——第一天 七大经典排序【上】 算法洗脑系列(8)算法洗脑系列(8篇)——第八篇 概率思想 算法洗脑系列(8篇)——第七篇 动态规划 算法洗脑系列(8篇)——第六篇 回溯思想 算法洗脑系列(8篇)——第五篇 分治思想 算法洗脑系列(8篇)——第四篇 枚举思想 算法洗脑系列(8篇)——第三篇 贪心思想 算法洗脑系列(8篇)——第二篇 递归思想 算法洗脑系列(8篇)——第一篇 递推思想 天籁数学(3)天籁数学——数列篇(3) 天籁数学——数列篇(2) 天籁数学——数列篇(1) 图形图像(1)玩玩图形图像——第一篇:图片灰度化 小爬虫系列(4)玩玩小爬虫——抓取时的几个小细节 玩玩小爬虫——抓取动态页面 玩玩小爬虫——试搭小架构 玩玩小爬虫——入门
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值