算法

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

时间复杂度

衡量算法性能的好坏的方式:时间复杂度
时间复杂度:量化算法执行步骤的数量,评估执行程序所需的时间,时间复杂度越来越大,执行的效率越来越低
空间复杂度:评估执行程序所需的存储空间
大O记法来表示时间复杂度:
*将时间复杂度执行步骤数量对应表达式(2n+n**2)中最有意义的一项提取出来放置在O后里面的括号里即可
*O(n**2)

冒泡排序

#1.乱序系列中的两两元素进行大小比较,将比较出较大的元素逐步向后偏移(序列中最大的值就已经偏移到最后了)
# def sort(alist):
#     for i in range(len(alist)-1):#控制元素两两比较的次数
#         if alist[i] > alist[i+1]:
#             alist[i],alist[i+1] = alist[i+1],alist[i]
#     return alist

#2.将第一步的操作继续一次作用在前n个乱序的序列中
def sort(alist):
    for j in range(len(alist)-1):
        for i in range(len(alist)-1-j):#控制元素两两比较的次数
            if alist[i] > alist[i+1]:
                alist[i],alist[i+1] = alist[i+1],alist[i]
    return alist
alist = [3,8,5,7,6,2,1]
print(sort(alist))

面向对象实例

栈:先进后出

#
class Stack(): #先进后出
    #入栈操作:从栈顶向栈底添加元素
    #出栈:从栈顶向栈底取元素
    def __init__(self): #添加一个列表的属性,让其充当栈的容器
        self.items = []
    def push(self,item):
        self.items.append(item)
    def pop(self):
        return self.items.pop()
    def length(self):
        return len(self.items)
    def isEmpty(self):
        return self.items == []

stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)
print(stack.length())
print(stack.isEmpty())
print(stack.pop())
print(stack.pop())
print(stack.pop())

队列:先进先出

#队列
class Queue():
    def __init__(self):
        self.items = []
    #入队列操作:从队尾向对头添加元素
    def enqueue(self,item):
        self.items.insert(0,item)
    #出队列:从对头取元素
    def dequeue(self):
        return self.items.pop()
    def length(self):
        return len(self.items)
    def isEmpty(self):
        return self.items == []
q = Queue()
for i in range(5):
    q.enqueue(i)
for i in range(5):
    print(q.dequeue())

队列例题:烫手的山芋

6个孩子排队围成一个圈,在计时器计时1s的时候,第一个孩子手里有一个山芋,开始计时,每计时1s,将山芋传递给下一个孩子,当计时器计时7s的时候,手中有山芋的孩子淘汰出游戏,游戏继续,直到剩下最后一个孩子,则该小孩获胜.

分析: 一轮游戏山芋被传递了几次:6次

因为每一轮游戏都需要淘汰一个小孩,基于队列的机制,每次只可以将对头元素取出,所以,要保证,山芋每次传递后,都要在队头孩子手里(山芋不动,人动)

class Queue():
    def __init__(self):
        self.items = []
    #入队列操作:从队尾向对头添加元素
    def enqueue(self,item):
        self.items.insert(0,item)
    #出队列:从对头取元素
    def dequeue(self):
        return self.items.pop()
    def length(self):
        return len(self.items)
    def isEmpty(self):
        return self.items == []
kids = ['A','B','C','D','E','F']
queue = Queue()
#将6个小孩入队列
for kid in kids:
    queue.enqueue(kid) #A是队头

while queue.length() > 1:
    #设计一轮游戏的实现
    for i in range(6): #控制山芋在一轮游戏中传递的次数
        popItem = queue.dequeue() #出队列
        queue.enqueue(popItem)#入队列
    queue.dequeue()

print(queue.dequeue())

面试题:如何使用两个栈的数据结构实现队列先进先出的效果!

class Stack1():
    def __init__(self):
        self.alist = []
        self.alist2 = []

    # 进栈
    def append(self,item):
        self.alist.append(item)

    # 出栈-->入栈
    def pop(self):
        res = self.alist.pop()
        # print(res)
        self.alist2.append(res)

    # 出栈
    def pop2(self):
        res = self.alist2.pop()
        print(res)

s1 = Stack1()

l = [8,6,9,2,4,3]
for i in l:
    s1.append(i)
    # print(i)

for i in range(6):
    s1.pop()

for i in range(6):
    s1.pop2()
百度:
class Solution:
    def __init__(self):
        self.stack1 = []
        self.stack2 = []

    def push(self, node):
        # 进栈
        self.stack1.append(node)

    def pop(self):
        # if self.stack2 == []:
        #     return None
        # else:
        for i in range(len(self.stack1)):
            self.stack2.append(self.stack1.pop())  # 出栈-->进栈
        out = self.stack2.pop()
        # for j in range(len(self.stack2)):
            # self.stack1.append(self.stack2.pop())
            # print(self.stack2.pop())
        return out


s1 = Solution()
for i in range(5):
    s1.push(i)
for j in range(5):
    print(s1.pop())

如何使用两个队列的数据结构实现栈先进后出的效果!

class Queue():
    def __init__(self):
        self.queueA=[]
        self.queueB=[]
    def push(self, node):
        self.queueA.append(node)  # 进队
    def pop(self):
        if len(self.queueA)==0:
            return None
        while len(self.queueA)!=1:
            self.queueB.append(self.queueA.pop(0))  # 出队 ---> 进队
        self.queueA,self.queueB=self.queueB,self.queueA #交换是为了下一次的pop
        return self.queueB.pop()
        
q1 = Queue()
for i in range(5):
    q1.append(i)

for j in range(5):
    print(q1.pop())

链表

1、链表和列表的区别是什么?

*列表内存分配是连续的,可以应用索引的机制

*链表内存分配是不连续的,没有索引机制

列表的弊端:

应用场景:需要高频对列表发起元素的添加和删除

当需要将添加元素或者删除元素后续的元素整体向前或者向后进行偏移移动,势必会消耗计算机的算力

链表的应用场景:高频进行元素的添加和删除

2、实现链表的数据结构(内存空间是不连续的)

封装两种不同形式的数据结构:

1)节点Node:存储单个的元素数据

class Node():
    def __init__(self,item):
        self.item = item
        self.next = None
n1 = Node(1)

2)链表Link:用于有序组织所有的节点

class Link():
    # 构建一个空链表
    def __init__(self):
        self.head = None
link = Link()

3、链表的完整实现:

class Node():
    def __init__(self,item):
        self.item = item
        self.next = None

class Link():
    # 构建一个空链表
    def __init__(self):
        self.head = None

    # 每次都向链表的头部添加节点(insert(0))
    def addByHead(self,item):
        node = Node(item)
        node.next = self.head  # 将插入的节点指向原始的头节点
        self.head = node    # 新添加的节点就是头节点

    # 遍历链表
    def travel(self):
        cur = self.head  # 定义一个变量cur,让其指向头节点
        while cur:  # 当cur.next为0时,循环结束
            print(cur.item) # 输出cur所指向节点的值
            cur = cur.next # cur向后偏移

    # 向链表尾部添加节点
    def append(self,item):
        node = Node(item)
        if self.isEmpty():  # 判断链表是否为空
            self.head = node
            return
        # 链表非空时
        cur = self.head    # cur指向头节点
        per = None       # 永远指向cur前一个节点
        while cur:      # cur.next为空(无节点)时,循环结束
            per = cur
            cur = cur.next
        per.next = node    # 循环结束时,pre一定指向的是链表的最后一个字节

    # 判断链表是否为空
    def isEmpty(self):
        return self.head == None

    # 返回链表中节点的数量
    def size(self):
        cur = self.head
        count = 1
        while cur:
            cur = cur.next
            count +=1
        return count
        
    # 向任意位置添加节点
    def insertNode(self,item,pos):  # pos为0,1,2类似索引位置
        node = Node(item)
        if pos == 0:      # 如果添加头节点
            self.addByHead(item)
            return

        cur = self.head    # 如果在节点间添加新节点
        per = None    # per永远指向cur的前一个节点
        for i in range(pos): # 数值pos刚好为cur移动次数
            per = cur
            cur = cur.next
        per.next = node
        node.next = cur


    # 删除指定节点
    def removeNode(self,item):
        cur = self.head
        per = None

        # 如果删除头节点
        if item == self.head.item:
            self.head = self.head.next
            return
        # 如果删除的不是头节点
        while cur:
            per = cur
            cur = cur.next
            if cur.item == item:
                per.next = cur.next
                return

link = Link()
link.addByHead(1)
link.addByHead(2)
link.addByHead(3)
link.addByHead(4)
# link.insertNode(66,4)
# link.append(5)
# link.removeNode(4)
link.travel()
# link.size()

二叉树

1、基本概念:

1)根节点:树状结构中最上层的那一个节点

2)左右叶子节点:一个节点分叉出左右两个子节点

3)子树:

*完整的子树:根节点和左右叶子节点组成

*不完整子树:根节点+左叶子节点

根节点+右叶子节点

根节点

4)如区分不同的子树:根据子树的根节点来区别不同的子树

2、节点封装

class Node():
    def __init__(self,item):
        self.item = item
        self.left = None
        self.right = None

3、完整功能代码

class Node(): # 创建节点
    def __init__(self,item):
        self.item = item
        self.left = None
        self.right = None

class Tree():
    def __init__(self):
        self.root = None  # 树的根节点初始化
    def addNode(self,item):
        node = Node(item)
        #树空的时候
        if self.root == None:
            self.root = node
            return
        #树为非空
        cur = self.root    
        node_list = [cur]   # 将根节点存入列表
        while node_list:
            pop_node = node_list.pop(0)  # 每次取列表的第一个值
            if pop_node.left != None:# 如果取出来值有左节点
                node_list.append(pop_node.left) # 添加进列表
            else: #如果左节点为空,则添加到值的左节点处
                pop_node.left = node 
                return
            if pop_node.right != None: #如果取出来的值有右节点
                node_list.append(pop_node.right)
            else:  # 如果右节点为空,则将值添加到右节点
                pop_node.right = node
                return

    # 判断值是否存在二叉树中
    def findNode(self,item):
        find = False   # 初始值
        cur = self.root
        node_list = [cur] # 将根节点存于列表中

        while node_list:
            pop_node = node_list.pop(0) # 取列表的第一个值
            if pop_node.item == item:
                find = True
                break
            else:
                if pop_node.left != None: #左节点不为空加入列表
                    node_list.append(pop_node.left)
                if pop_node.right != None:#右节点不为空加入列表
                    node_list.append(pop_node.right)
        return find

    def traval(self): # 遍历树
        cur = self.root
        node_list = [cur]

        while node_list:
            pop_node = node_list.pop(0)
            print(pop_node.item)
            if pop_node.left != None:#左节点不为空加入列表
                node_list.append(pop_node.left)
            if pop_node.right != None:#右节点不为空加入列表
                node_list.append(pop_node.right)

tree = Tree()
for i in range(1,7):
    tree.addNode(i)
print(tree.findNode(61))

4、二叉树的遍历

*广度遍历:上述代码的travel就是广度遍历(逐层遍历)

*深度遍历:要将一颗二叉树中所有的子树依次按照下述三种方法进行遍历即可(前中后序遍历是需要依次作用在每一颗子树中)

前序:根左右

中序:左根右

后序:左右根

对一个二叉树从低到高排序:

class SortTree():
    def __init__(self):
        self.root = None
    # 向树中插入值,左节点存放比根节点小或相等的值,右节点存放比根节点大的值
    def insertNode(self,item):
        node = Node(item)
        #树为空时
        if self.root == None:
            self.root = node
            return
        #树为非空时
        cur = self.root
        while True:
            #插入节点比比较的节点的值小,则插入到其左侧,否则插入到其右侧
            if node.item >= cur.item: #往右插
                if cur.right == None:
                    cur.right = node
                    return
                else:#右节点当作根节点继续比较
                    cur = cur.right
            else: #往左插
                if cur.left == None:
                    cur.left = node
                    return
                else:#左节点当作根节点继续比较
                    cur = cur.left

    def middle(self,root): #中序遍历:左根右
        if root == None:
            return
        self.middle(root.left) #
        print(root.item) #
        self.middle(root.right) #
tree = SortTree()
alist = [3,8,5,7,6,2,1]
for item in alist:
    tree.insertNode(item)
tree.middle(tree.root)

posted @ 2021-10-12 15:20  多啦a梦与时光机  阅读(44)  评论(0编辑  收藏  举报