数据结构 --- 01. 时间复杂度,timeit模块,栈,队列,双端队列

一.时间复杂度

  1.基本概念

评判程序优劣的方法:
  消耗计算机资源和执行效率(无法直观)
  计算算法执行的耗时(适当推荐,因为会受机器和执行环境的影响)
  时间复杂度(推荐)
时间复杂度
  评判规则:量化算法执行的操作/执行步骤的数量
  最重要的项:时间复杂度表达式中最有意义的项
  大O记法:O(时间复杂度表达式中最有意义的项)

常见的时间复杂度:
  • O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)
 

  2.示例说明

a=5
b=6
c=10
for i in range(n):
   for j in range(n):
      x = i * i
      y = j * j
      z = i * j
for k in range(n):
   w = a*k + 45
   v = b*b
d = 33
3+3n**2+2n+1

用大O记法:O(n**2)

def sumOfN(n):
    theSum = 0
    for i in range(0,n+1):
        theSum = theSum + i

    return theSum

print(sumOfN(10))
用大O记法:

O(n)

③三种不同数据结构的时间复杂度

[
    [‘tom‘,100],[‘jay‘,99]
]
#O(n)
[
    (‘tom‘,100),(‘jay‘,99)
]
#O(n)
{
    ‘tom‘:{‘score‘:100},
    ‘jay‘:{‘score‘:100},
}
#O(1)

二.timeit(测试代码执行的平均值)

timeit模块:该模块可以用来测试一段python代码的执行速度/时长。      计算运行平均耗时

Timer类:该类是timeit模块中专门用于测量python代码的执行速度/时长的。原型为:class timeit.Timer(stmt=‘pass‘,setup=‘pass‘)。

  stmt参数:表示即将进行测试的代码块语句。

  setup:运行代码块语句时所需要的设置。

  timeit函数:timeit.Timer.timeit(number=100000),该函数返回代码块语句执行number次的平均耗时。
示例:实例化一个空列表,然后将0-n范围的数据添加到列表中。
from timeit import Timer
def test01():
    alist = []
    for i in range(1000):
        alist.append(i)
def test02():
    alist = []
    for i in range(1000):
        alist += [i]
def test03():
    alist = [i for i in range(1000)]
def test04():
    alist = list(range(1000))
def test05():
    alist = []
    for i in range(1000):
        alist.insert(i,i)
if __name__ == ‘__main__‘:
    timer = Timer(stmt=‘test01()‘,setup=‘from __main__ import test01‘)
    print(timer.timeit(1000))

    timer = Timer(stmt=‘test02()‘,setup=‘from __main__ import test02‘)
    print(timer.timeit(1000))

    timer = Timer(stmt=‘test03()‘,setup=‘from __main__ import test03‘)
    print(timer.timeit(1000))

    timer = Timer(stmt=‘test04()‘,setup=‘from __main__ import test04‘)
    print(timer.timeit(1000))

    timer = Timer(stmt=‘test05()‘,setup=‘from __main__ import test05‘)
    print(timer.timeit(1000))
结果:

0.0837575913687374
0.08196741393689422
0.03640777904436732
0.014782621075369207
0.16312698009613769

三.  栈

特性:先进后出的数据结构

  1.基本操作

Stack() 创建一个空的新栈。 它不需要参数,并返回一个空栈。
push(item)将一个新项添加到栈的顶部。它需要 item 做参数并不返回任何内容。
pop() 从栈中删除顶部项。它不需要参数并返回 item 。栈被修改。
peek() 从栈返回顶部项,但不会删除它。不需要参数。 不修改栈。
isEmpty() 测试栈是否为空。不需要参数,并返回布尔值。
size() 返回栈中的 item 数量。不需要参数,并返回一个整数。

  2.示例:

class Stack():
    def __init__(self):
        self.items = []
    def push(self,item):
        self.items.append(item)
    def pop(self):
        return self.items.pop()
    def peek(self):
        return self.items[-1]
    def isEmpty(self):
        return self.items == []
    def size(self):
        return len(self.items)

s = Stack()
s.push(‘jay‘)
s.push(123)
s.push(‘haha‘)
print(s.pop())
print(s.pop())
print(s.isEmpty())
print(s.size())
print(s.peek())
结果:

haha
123
False
1
jay

应用:每个 web 浏览器都有一个返回按钮。当你浏览网页时,这些网页被放置在一个栈中(实际是网页的网址)。

你现在查看的网页在顶部,你第一个查看的网页在底部。如果按‘返回’按钮,将按相反的顺序浏览刚才的页面。
s = Stack()
def request(url):
    s.push(url)
def back():
    return s.pop()
def current_page():
    print(s.pop())

request(‘www.1.com‘)
request(‘www.2.com‘)
request(‘www.3.com‘)

current_page()
back()
back()
结果:

www.3.com
‘www.1.com‘

四. 队列

  1.基本概念

队列:先进先出
应用场景:
    我们的计算机实验室有 30 台计算机与一台打印机联网。当学生想要打印时,    他们的打印任务与正在等待的所有其他打印任务“一致”。第一个进入的任务是先完成。    如果你是最后一个,你必须等待你前面的所有其他任务打印

  2.基本操作

Queue() 创建一个空的新队列。 它不需要参数,并返回一个空队列。
enqueue(item) 将新项添加到队尾。 它需要 item 作为参数,并不返回任何内容。
dequeue() 从队首移除项。它不需要参数并返回 item。 队列被修改。
isEmpty() 查看队列是否为空。它不需要参数,并返回布尔值。
size() 返回队列中的项数。它不需要参数,并返回一个整数。

  3.示例

class Queue():
    def __init__(self):
        self.items = []
    def enqueue(self,item):
        self.items.insert(0,item)
    def dequeue(self):
        return self.items.pop()
    def isEmpty(self):
        return self.items == []
    def size(self):
        return len(self.items)
q = Queue()
q.enqueue(1)
q.enqueue(2)
q.enqueue(3)

print(q.dequeue())
print(q.dequeue())
结果:

1
2

案例:烫手的山芋
  烫手山芋游戏介绍:6个孩子围城一个圈,排列顺序孩子们自己指定。  第一个孩子手里有一个烫手的山芋,需要在计时器计时1秒后将山芋传递给下一个孩子,  依次类推。规则是,在计时器每计时7秒时,手里有山芋的孩子退出游戏。该游戏直到剩下一个孩子时结束,  最后剩下的孩子获胜。请使用队列实现该游戏策略,排在第几个位置最终会获胜。

q = Queue()
alist = [‘a‘,‘b‘,‘c‘,‘d‘,‘e‘,‘f‘]
for i in alist:
    q.enqueue(i)

while q.size() > 1:
    for i in range(6):
        kid = q.dequeue()
        q.enqueue(kid)
    q.dequeue()

print(q.dequeue())
结果:

    e

五,双端队列

同同列相比,有两个头部和尾部。可以在双端进行数据的插入和删除,提供了单数据结构中栈和队列的特性

  1.基本操作

Deque() 创建一个空的新 deque。它不需要参数,并返回空的 deque。
addFront(item) 将一个新项添加到 deque 的首部。它需要 item 参数 并不返回任何内容。
addRear(item) 将一个新项添加到 deque 的尾部。它需要 item 参数并不返回任何内容。
removeFront() 从 deque 中删除首项。它不需要参数并返回 item。deque 被修改。
removeRear() 从 deque 中删除尾项。它不需要参数并返回 item。deque 被修改。
isEmpty() 测试 deque 是否为空。它不需要参数,并返回布尔值。
size() 返回 deque 中的项数。它不需要参数,并返回一个整数。

  2.示例:回文检查

双端队列应用案例:回文检查
回文是一个字符串,读取首尾相同的字符,例如,radar toot madam。
class Deque():
    def __init__(self):
        self.items = []
    def addFont(self,item):
        self.items.append(item)
    def addRear(self,item):
        self.items.insert(0,item)
    def removeFont(self):
        return self.items.pop()
    def removeRear(self):
        return self.items.pop(0)
    def isEmpty(self):
        return self.items == []
    def size(self):
        return len(self.items)
def isHuiWen(word):
    ex = True
    q = Deque()
    for ch in word:
        q.addFont(ch)
    while q.size() > 1:
        if q.removeFont() != q.removeRear():
            ex = False
            break
    return ex
print(isHuiWen(‘abbaa‘))
结果:

False

原文地址:https://www.cnblogs.com/sc-1067178406/p/10960510.html

时间: 2024-10-26 21:55:11

数据结构 --- 01. 时间复杂度,timeit模块,栈,队列,双端队列的相关文章

【C/C++学院】0828-STL入门与简介/STL容器概念/容器迭代器仿函数算法STL概念例子/栈队列双端队列优先队列/数据结构堆的概念/红黑树容器

STL入门与简介 #include<iostream> #include <vector>//容器 #include<array>//数组 #include <algorithm>//算法 using namespace std; //实现一个类模板,专门实现打印的功能 template<class T> //类模板实现了方法 class myvectorprint { public: void operator ()(const T &

《算法实战策略》-chaper19-队列、栈和双端队列

对于计算机专业的学生来说,他们一定会很熟悉一句话:程序设计 = 算法 + 数据结构.而根据笔者的理解,所谓程序设计其实就是为了编程解决实际问题,所谓算法是一种解决问题某种思维的方法,但是思维需要得到编程实践,这就需要基于数据结构.一个好的数据结构能够让我们更快更高效得处理数据,有些模拟性.数学背景并不深厚的的问题,仅仅基于高效的数据结构就可以解决.那么这一章节,我们就单独将队列.栈.双端队列拿出来,结合具体的题目,看看它们是如何灵活的运用到解题策略当中的. 考虑到笔者在<入门经典>和<啊

两个栈实现双端队列

一个笔试题,当时竟然没想出来,现在实现下 1 /* 2 用两个栈实现双端队列 3 栈s1,s2. 4 pushback()和popback(),必须在s2为空的情况,把s2的都放s1中 5 pushfront()和popfront(),必须是在s1为空,把s1的都给放到s2中 6 */ 7 #include <iostream> 8 #include <stack> 9 using namespace std; 10 template <typename T> 11 c

nyoj1117 鸡蛋队列 (双端队列,deque)

题目1117 题目信息 运行结果 本题排行 讨论区 鸡蛋队列 时间限制:1000 ms  |  内存限制:65535 KB 难度:1 描述 将两根筷子平行的放在一起,就构成了一个队列.将带有编号的鸡蛋放到两根筷子之间叫做入队(push),将筷子之间的鸡蛋拿出来叫做出队(pop).但这两种方式有特殊的定义,对于入队,只能将鸡蛋从队列的尾部向里放入:对于出队,只能将鸡蛋从队列的头部向外将鸡蛋拿出来. 将①.②入队: 头____________尾                         ___

双端队列deque的应用

collections模块作为基础数据类型的一种扩展,提供了更为丰富的数据结构支持.和list相比,双端队列deque在数组的首部和尾部进行增加和删除元素的时间复杂度都为O(1).而list在数组尾部进行操作的时间复杂度为O(1),在首部进行增加删除数据的时间复杂度为O(n)(涉及到整个数组元素的移动). Deques支持线程安全,内存有效的在队列两端进行删除增加元素操作,在任一方向上具有大致相同的O(1)性能. 类原型:collections.deque([iterable[, maxlen]

PHP双向队列,双端队列代码

<?php /**  * User: jifei  * Date: 2013-07-30  * Time: 23:12 */ /**  * PHP实现双向队列,双端队列  * 双端队列(deque,全名double-ended queue)是一种具有队列和栈性质的数据结构.  * 双端队列中的元素可以从两端弹出,插入和删除操作限定在队列的两边进行.  */ class Deque {     public $queue=array();     /**      * 构造函数初始化队列     

python基础教程_学习笔记19:标准库:一些最爱——集合、堆和双端队列

标准库:一些最爱 集合.堆和双端队列 集合 集合Set类位于sets模块中. >>> range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> set(range(10)) set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 集合是由序列(或其他可迭代的对象)构建的.主要用于检查成员资格,因此,副本是被忽略的: >>> range(10)*2 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9

UVa 210 Concurrency Simulator(双端队列)

题意  模拟程序并行运行 STL队列 双端队列 的应用  用双端队列维护即将执行的程序  再用个队列维护等待变量释放的程序   用lock表示变量锁定状态 先将所有程序依次放到执行队列中  每次取出队首程序运行不超过lim时间  未运行完又放到执行队列队尾 遇到lock时  若当前锁定状态为false就将锁定状态变为true  否则将当前程序放到等待队列队尾并结束运行 遇到unlock时  若等待队列有程序  就将等待队列队首程序放到执行队列队首 遇到end时 退出当前执行(不再进队尾) #in

数据结构与算法分析 3.26 — 双端队列的实现

一.题目 编写支持双端队列的例程,插入与弹出操作均花费 O(1)时间 二.解答 双端队列(deque,全名double-ended queue)是一种具有队列和栈性质的数据结构. 双端队列中的元素可以从两端弹出,插入和删除操作限定在队列的两边进行. 基本操作:在双端队列两端插入与删除. ADT术语: Capacity:数组容量 Left:队列左端,指向队列左边第一个元素 Right:队列右端,指向队列右边最后一个元素的下一个位置 初始化:Left = Right = 0: 判空:   Left