zoukankan      html  css  js  c++  java
  • Python——数据结构(栈,队列,链表)

    数据结构

    程序=数据结构+算法

    数据结构就是设计数据以何种方式组织并存储在计算机中。列表、集合与字典等都是一种数据结构。

    小Tips:列表中的元素是怎样存储的,操作的时间复杂度是多少?

    Python将数存放在一个内存单元中,在列表中的元素指向那个内存单元。所以列表中的元素在内存单元中可能在一起,也可能不在一起。
    
    [].insert()和[].remove()的时间复杂度为o(n)
    [].append()和[].pop()的时间复杂度为o(1)

    栈(Stack)是一个数据集合,可以理解为只能在一端进行插入或删除操作的列表。

    栈的特点:后进先出

    栈的基本操作:

    • 进栈(压栈):push
    • 出栈:pop
    • 取栈顶(看看栈顶是谁):gettop 

    Python中实现栈:

    进栈函数:append
    出栈函数:pop
    查看栈顶函数:li[-1]

    小Tips:

    递归出错的原因是:爆栈

    示例:给一个字符串,其中包含小括号、中括号、大括号,求该字符串中的括号是否匹配。

    思路:检查字符串是否包含"{","[","("如果包含则将其入栈,遇到"}","]",")"时检查当前栈顶,相同则将其出栈,否则返回False

     1 def check_kuohao(str):
     2     stack = []
     3     for i in str:
     4         if i in {'{','[','('}:
     5             stack.append(i)
     6         elif i == '}':
     7             if len(stack) > 0 and stack[-1] == '{':
     8                 stack.pop()
     9             else:
    10                 return False
    11         elif i == ']':
    12             if len(stack) > 0 and  stack[-1] == '[':
    13                 stack.pop()
    14             else:
    15                 return False
    16         elif i == ')':
    17             if len(stack) > 0 and stack[-1] == '(':
    18                 stack.pop()
    19             else:
    20                 return False
    21 
    22     if len(stack) == 0:
    23         return True
    24     else:
    25         return False
    26 
    27 print(check_kuohao('([)]'))
    View Code

    示例:迷宫问题(深度优先,一条路走到黑)

    maze = [
        [1,1,1,1,1,1,1,1,1,1],
        [1,0,0,1,0,0,0,1,0,1],
        [1,0,0,1,0,0,0,1,0,1],
        [1,0,0,0,0,1,1,0,0,1],
        [1,0,1,1,1,0,0,0,0,1],
        [1,0,0,0,1,0,0,0,0,1],
        [1,0,1,0,0,0,1,0,0,1],
        [1,0,1,1,1,0,1,1,0,1],
        [1,1,0,0,0,0,0,0,0,1],
        [1,1,1,1,1,1,1,1,1,1]
    ]
    
    def mazepath(x1,y1,x2,y2):
        dirs = [
                # lambda 参数1,参数2:(返回值格式)
                lambda x, y: (x + 1, y),    # 向下走一格
                lambda x, y: (x - 1, y),    # 向上走一格
                lambda x, y: (x, y - 1),    # 向左走一格
                lambda x, y: (x, y + 1)     # 向右走一格
                ]
        stack = []    # 初始化一个栈
        stack.append((x1,y1))   # 将起始坐标推入栈中
        while len(stack) > 0:
            curNode = stack[-1]     # 查看栈顶元素
            if curNode[0] == x2 and curNode[1] == y2:   # 到达终点
                for i in stack:
                    print(i)
                return True
            else:
                for d in dirs:
                    nextNode = d(curNode[0],curNode[1])     # 将()中的元素做相应的操作,还没推入栈中
                    if maze[nextNode[0]][nextNode[1]] == 0:    # 这条路可以走
                        stack.append(nextNode)  # 将这个新位置入栈
                        maze[nextNode[0]][nextNode[1]] = -1  # 将新位置标记为已经走过,防止死循环
                        break
                else:   # 当前位置上下左右都不能走,后退一步
                    stack.pop()
        return False    # 栈为空,无路可走
    
    print(mazepath(1,1,8,8))
    

    队列

    队列(Queue)是一个数据集合,仅允许在列表的一端进行插入,另一端进行删除。

    进行插入的一端称为队尾(rear),插入动作称为进队或入队,进行删除的一端称为队头(front),删除动作称为出队

    队列的性质:先进先出

    双向队列:队列的两端都允许进行进队和出队操作。

    队列的实现原理:

    初步设想:列表+两个下标指针

    创建一个列表和两个变量,front变量指向队首,rear变量指向队尾。初始时,front和rear都为0。

    进队操作:元素写到li[rear]的位置,rear自增1。

    出队操作:返回li[front]的元素,front自减1。

    这样队列会不够用,所以我可以把它的首尾连接起来。

    环形队列:

    实现方式:求余数运算

    队首指针前进1:front = (front + 1) % MaxSize

    队尾指针前进1:rear = (rear + 1) % MaxSize

    队空条件:rear == front

    队满条件:(rear + 1) % MaxSize == front

    Python实现队列:

    from collections import deque  # 双向队列
    创建队列:queue = deque(li)
    进队:append
    出队:popleft
    双向队列队首进队:appendleft
    双向队列队尾进队:pop

    示例:迷宫问题(广度优先)

    思路:从一个节点开始,寻找所有下面能继续走的点。继续寻找,直到找到出口。

     1 from collections import  deque
     2 
     3 mg = [
     4     [1,1,1,1,1,1,1,1,1,1],
     5     [1,0,0,1,0,0,0,1,0,1],
     6     [1,0,0,1,0,0,0,1,0,1],
     7     [1,0,0,0,0,1,1,0,0,1],
     8     [1,0,1,1,1,0,0,0,0,1],
     9     [1,0,0,0,1,0,0,0,0,1],
    10     [1,0,1,0,0,0,1,0,0,1],
    11     [1,0,1,1,1,0,1,1,0,1],
    12     [1,1,0,0,0,0,0,1,0,1],
    13     [1,1,1,1,1,1,1,1,1,1]
    14 ]
    15 
    16 dirs = [lambda x, y: (x + 1, y),
    17         lambda x, y: (x - 1, y),
    18         lambda x, y: (x, y - 1),
    19         lambda x, y: (x, y + 1)]
    20 
    21 def print_p(path):
    22     curNode = path[-1]
    23     realpath = []
    24     print('迷宫路径为:')
    25     while curNode[2] != -1:
    26         realpath.append(curNode[0:2])
    27         curNode = path[curNode[2]]
    28     realpath.append(curNode[0:2])
    29     realpath.reverse()
    30     print(realpath)
    31 
    32 def mgpath(x1, y1, x2, y2):
    33     queue = deque()
    34     path = []
    35     queue.append((x1, y1, -1))
    36     while len(queue) > 0:
    37         curNode = queue.popleft()
    38         path.append(curNode)
    39         if curNode[0] == x2 and curNode[1] == y2:
    40             #到达终点
    41             print_p(path)
    42             return True
    43         for dir in dirs:
    44             nextNode = dir(curNode[0], curNode[1])
    45             if mg[nextNode[0]][nextNode[1]] == 0:  # 找到下一个方块
    46                 queue.append((*nextNode, len(path) - 1))
    47                 mg[nextNode[0]][nextNode[1]] = -1  # 标记为已经走过
    48     return False
    49 
    50 
    51 mgpath(1,1,8,8)
    View Code

    链表

    链表中每一个元素都是一个对象,每个对象称为一个节点,包含有数据域key和指向下一个节点的指针next。通过各个节点之间的相互连接,最终串联成一个链表。

    定义节点:

    class Node(object):
        def __init__(self, item):
            self.item = item    # 当前节点的值
            self.next = None    # 下一节点的值
    
            
    a = Node(1)
    b = Node(2)
    c = Node(3)
    
    a.next = b
    b.next = c  

    链表节点的插入和删除

    插入:
    p.next = curNode.next
    curNode.next = p
    
    删除:
    p = curNode.next
    curNode.next = curNode.next.next
    del p
    

    建立链表:

    头插法

    def createLinkListF(li):
        l = Node()
        for num in li:
            s = Node(num)
            s.next = l.next
            l.next = s
        return l  

    尾插法

    def createLinkListR(li):
        l = Node()
        r = l       #r指向尾节点
        for num in li:
            s = Node(num)
            r.next = s
            r = s
    

    双链表

    双链表中每个节点有两个指针:一个指向后面节点、一个指向前面节点。
    节点定义:

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

    插入和删除 

    插入:
    p.next = curNode.next
    curNode.next.prior = p
    p.prior = curNode
    curNode.next = p
    删除:
    p = curNode.next
    curNode.next = p.next
    p.next.prior = curNode
    del p
    

    建立双链表

    def createLinkListR(li):
        l = Node()
        r = l
        for num in li:
            s = Node(num)
            r.next = s
            s.prior = r
            r = s
        return l, r
    
  • 相关阅读:
    7.12Java+TestNG环境搭建
    7.15Java之调用API接口传表单获取返回信息
    7.12理解Cookie与token
    7.13一次完整的Http请求过程(3)
    7.13一次完整的Http请求过程(2)
    7.13一次完整的Http请求过程
    PostgreSql安装(win 2003 下)
    实用工具(渐变更新中)
    .net Ajax系列(2)调用多Web Service
    .net Ajax系列(1)调用Web Service
  • 原文地址:https://www.cnblogs.com/x54256/p/8312938.html
Copyright © 2011-2022 走看看