zoukankan      html  css  js  c++  java
  • 算法 初识

    什么是算法 如何理解算法?

    算法就是对问题进行处理且求解的一种实现思路或者思想。

    • 一个常胜将军在作战之前都会进行战略的制定,目的是为了能够在最短的时间切成本消耗最低的情况下获取最终的胜利。如果将编码作为战场,则程序员就是这场战役的指挥官,你如何可以将你的程序可以在最短且消耗资源最小的情况下获取最终的执行结果呢?算法就是我们的策略!

    什么是算法分析?

    • 刚接触编程的学生经常会将自己编写的程序和别人的程序做比对,获取在比对的过程中会发现双方编写的程序很相似但又各不相同。那么就会出现一个有趣的现象:两组程序都是用来解决同一个问题的,但是两组程序看起来又各不相同,那么哪一组程序更好呢?
    • a+b+c = 1000 a2 + b2 = c**2 (a,b,c均为自然数),求出a,b,c可能的组合?
    for a in range(0,1001):
        for b in range(0,1001):
            for c in range(0,1001):
                if a**2 + b**2 == c**2 and a+b+c==1000:
                    print(a,b,c)

    代码二

    for a in range(0,1001):
        for b in range(0,1001):
            c = 1000 - a - b
            if a**2 + b**2 == c**2 and a+b+c==1000:
                print(a,b,c)

    可以看出 相同的结果 不同的代码 时长不一样

    评判程序优势的方法

    • 消耗计算机资源和执行效率(无法直观)
    • 计算算法执行的耗时(适当推荐,因为会受机器和执行环境的影响)
    • 时间复杂度(推荐)

    时间复杂度:

    • 评判规则:量化算法执行的操作/执行步骤的数量
    • 最重要的项:时间复杂度表达式中最有意义的项
    • 大O记法:O(时间复杂度表达式中最有意义的项)

    计算下列算法的时间复杂度

    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(n**2)

    常见的时间复杂度:

    • O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)

    数据结构

    • 案例: 需要存储一些学生的学生信息(name,score),那么这些数据应该如何组织呢?查询某一个具体学生的时间复杂度是什么呢?(三种组织方式)
    [
        ['tom',100],['jay',99]
    ]
    #O(n)
    [
        ('tom',100),('jay',99)
    ]
    #O(n)
    {
        'tom':{'score':100},
        'jay':{'score':100},
    }
    #O(1)

    如何测试代码性能?

    • timeit模块:该模块可以用来测试一段python代码的执行速度/时长。

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

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

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

      • timeit函数:timeit.Timer.timeit(number=100000),该函数返回代码块语句执行number次的

      • 计算运行平局耗时
      • 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.1200843300920747
        0.09542515960902793
        0.035514636978769026
        0.022534339526118885
        0.178243830964033

    先进后出的数据结构

    栈顶,栈尾

    Stack()创建一个空的新栈,他不需要参数,并返回一个空栈
    push(item)将一个新项添加到栈的顶部,它需要item做参数并不不返回任何内容
    pop()从栈中删除顶部的项,它不需要参数返回item,栈被修改
    peek()从栈返回顶部项,但不会删除
    isEmpty()测试栈是否为空,不需要参数,并返回布尔值
    size()返回栈中的item数量,不需要参数,并返回一个整数
    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('test1')
    s.push('test2')
    s.push('test3')
    print(s.pop())
    print(s.pop())
    print(s.peek())#返回栈的顶部
    print(s.isEmpty())#判断是否为空
    print(s.size())#返回栈的数量

    网页回滚

    s=Stack()
    def request(url):
        s.push(url)
    def back():
        print(s.pop())
    request('wwwbaidu1.com')
    request('www.baidu2.com')
    back()
    back()
    ######
    www.baidu2.com
    wwwbaidu1.com

    队列

    先进先出

    Queue()创建一个空的新队列,它不要参数

    enqueue(item)将新项添加到队尾,它需要item作为参数

    dequeue()从队首移除项,它不需要参数并返回item

    isEmpry()查看队列是否为空 并返回布尔值

    size()返回队列中的项书 并返回一个整数

    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.enquequ(1)
    q.enquequ(2)
    q.enquequ(3)
    print(q.dequeue())
    print(q.dequeue())

    1

    2

    烫手的山芋

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

    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()
    alist = ['a', 'b', 'c', 'd', 'e', 'f']
    for i in alist:
        q.enqueue(i)#把6个孩子加入队列
    
    while q.size() > 1:#循环队列大于一就跑
        for i in range(6):#次数
            kid = q.dequeue()#让对头的孩子退出队列
            q.enqueue(kid)#在让加入队列
        q.dequeue()#第6次之后 永久性退出循环
    #结束之后 把这个孩子取出
    print(q.dequeue())

    双端队列

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

     Deque()创建一个空的新deque,他不需要任何参数

    addFront(item)将一个新项添加到deque的首部,他需要item参数

    addRear(item)将一个新项添加到deque的尾部它需要iem参数

    removeFront()从deque中删除首项,它不需要参数并返回item

    removeRear()从deque中删除尾项,它不需要参数并返回item

    isEmpty()测试deque是否为空,它不需要参数,并返回布尔值

    size()返回deque中的项说,它不需要参数,并返回一个整数

    class Deque():#创建一个空的deque
        def __init__(self):
            self.items = []
        def addFont(self,item):#将一个新的项添加到deque首部
            self.items.append(item)
        def addRear(self,item):#将一个新的项添加dequ尾部
            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):#返回deque中的项数
            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('toot'))

    计算机存储理解

    • 指向:如果一个变量存储了某一块内存空间的地址,则表示该变量指向该块内存
    • 引用:如果一个变量存储了某一块内存空间的地址,则该变量可以成为该内存的一个引用

     

    顺序表

    • 容器中存储的元素是有顺序的,顺序表的结构可以分为两种形式:单数据类型和多数据类型。
    • python中的列表和元组就属于多数据类型的顺序表

     相同类型属性的列表 存储结构

     不相同类型属性的列表 存储结构

    链表

    相对于顺序表,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理且进行扩充时不需要进行数据搬迁。

    . is_empty():链表是否为空

    . length():链表长度

    . travel():遍历整个链表

    . add(item):链表头部添加元素

    . append(item):链表尾部添加元素

    . insert(pos, item):指定位置添加元素

    . remove(item):删除节点

    . search(item):查找节点是否存在

    add添加解

     travel遍历

    class Node():
        def __init__(self, item):
            self.item = item
            self.next = None  # 存储的链表中下一个节点的地址
    
    class Link():
        def __init__(self):
            # _head永远指向None或者第一个节点的地址
            self._head = None
    
        def add(self, item):
            node = Node(item)
            node.next = self._head#Node的self.next
            self._head = node
    
        def travel(self):
            # cur存储的就是第一个节点的地址
            cur = self._head
            while cur:
                print(cur.item)
                cur = cur.next
    link=Link()
    link.add(1)
    link.add(2)
    link.add(3)
    link.travel()

    回顾:

        def is_Empty(self):#判断联表是否为空
            return self._head == None
        def size(self):
            length = 0
            if self._head == None:#如果head是空 直接返回
                return length
            #cur就是指向了第一个节点
            cur = self._head
            while cur:#不为空循环
                length += 1
                cur = cur.next#一直向下查找
            return length

    append

        def append(self,item):
            node = Node(item)
            #如果链表为空则执行如下操作
            if self._head == None:
                self._head = node
                return
            
            cur = self._head#等于head头
            pre = None
            while cur:
                pre = cur#上一个
                cur = cur.next#下一个
            pre.next = node#当前插入值
            
        def search(self,item):
            ex = False
            
            cur = self._head
            while cur:
                if cur.item == item:#判断是否相等
                    ex = True
                    break
                cur = cur.next#不断的往下查找
            return ex

    insert

        def insert(self,pos,item):
            node = Node(item)
            
            if pos <= 0:#小于0add
                self.add(item)
                return
            if pos >= self.size():#大于等于链表的长度插入尾部
                self.append(item)
                return
            
            cur = self._head
            pre = None
            
            for i in range(0,pos):
                pre = cur
                cur = cur.next
            pre.next = node
            node.next = cur

     remove

        def remove(self,item):
            cur = self._head
            pre = None
            if cur.item == item:#删除第一个节点
                self._head = cur.next
                return
            while cur:
                pre = cur
                cur = cur.next#做遍历
                if cur.item == item:#意味着是我们想删除的节点
                    pre.next = cur.next#从c2划到c4
                    break

     总结:

    class Node():
        def __init__(self,item):
            self.item = item
            self.next = None #存储的链表中下一个节点的地址
    class Link():
        def __init__(self):
            #_head永远指向None或者第一个节点的地址
            self._head = None      
        def add(self,item):
            node = Node(item)
            node.next = self._head
            self._head = node
        def travel(self):
            #cur存储的就是第一个节点的地址
            cur = self._head
            while cur:
                print(cur.item)
                cur = cur.next
        def is_Empty(self):
            return self._head == None
        def size(self):
            length = 0
            if self._head == None:
                return length
            #cur就是指向了第一个节点
            cur = self._head
            while cur:
                length += 1
                cur = cur.next
            return length
        def append(self,item):
            node = Node(item)
            #如果链表为空则执行如下操作
            if self._head == None:
                self._head = node
                return
            
            cur = self._head
            pre = None
            while cur:
                pre = cur
                cur = cur.next
            pre.next = node
            
        def search(self,item):
            ex = False
            
            cur = self._head
            while cur:
                if cur.item == item:
                    ex = True
                    break
                cur = cur.next
            return ex
        def insert(self,pos,item):
            node = Node(item)
            
            if pos <= 0:
                self.add(item)
                return
            if pos >= self.size():
                self.append(item)
                return
            
            cur = self._head
            pre = None
            
            for i in range(0,pos):
                pre = cur
                cur = cur.next
            pre.next = node
            node.next = cur
        def remove(self,item):
            cur = self._head
            pre = None
            if cur.item == item:
                self._head = cur.next
                return
            while cur:
                pre = cur
                cur = cur.next
                if cur.item == item:
                    pre.next = cur.next
                    break

    link = Link()
    link.add(1)
    link.add(2)
    link.add(3)
    link.append(4)
    # link.insert(-2,'hello')
    link.remove(3)
    link.travel()

  • 相关阅读:
    可伸缩性/可扩展性(Scalable/scalability)
    广播变量与累加器
    swool配置ssl
    使用smb映射到本地时 访问权限,请联系管理员错误
    npm 安装cnpm淘宝镜像时报错解决
    在使用mysql8.0的时候遇到的密码链接问题
    配置ubuntu的超管账号密码
    nginx 配置laravel框架域名配置
    eclipse 下载安装单元测试log4j的配置与搭建
    eclipse安装Spring的具体步骤
  • 原文地址:https://www.cnblogs.com/zaizai1573/p/10961473.html
Copyright © 2011-2022 走看看