二、数据结构基础+栈+队列+迷宫问题

网友投稿 611 2022-11-22

二、数据结构基础+栈+队列+迷宫问题

二、数据结构基础+栈+队列+迷宫问题

文章目录

​​一、数据结构​​

​​1.数据结构分类​​​​2.列表/数组​​

​​二、栈​​

​​1.栈的实现​​​​2.小应用:括号匹配问题​​

​​三、队列​​

​​1.队列的实现​​​​2.双向队列​​

​​四、迷宫问题​​

​​1.栈——深度优先搜索​​​​2.队列——广度优先搜索​​

​​五、视频链接​​

一、数据结构

数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中元素之间的关系组成。 简单来说,数据结构就是设计数据以何种方式组织并存储在计算机中。 比如:列表、集合与字典等都是一种数据结构。 N.Wirth: “程序=数据结构+算法”

1.数据结构分类

数据结构按照其逻辑结构可分为线性结构、树结构、图结构 线性结构:数据结构中的元素存在一对一的相互关系 树结构:数据结构中的元素存在一对多的相互关系 图结构:数据结构中的元素存在多对多的相互关系

2.列表/数组

列表(其他语言称数组)是一种基本数据类型。 关于列表的问题: Q1:表中的元素是如何存储的? A1:线性存储。在内存中,数组存储的元素的值,而列表存储的是列表元素的地址。 Q2:列表的基本操作:按下标查找、插入元素、删除元素……这些操作的时间复杂度是多少? A2: 插入元素的内置方法:insert 删除元素的内置方法:pop、remove 若pop删除的是最后一个元素,则O(1) 否则为O(n),n为列表长度 插入和删除后,原列表需要进行重新的复位,需要花费时间,所以时间复杂度为O(n) 扩展:python的列表是如何实现的? 数组和列表的区别: 1.数组元素类型都一致 2.数组大小固定 列表中存储的是列表元素的地址,因为地址在计算机中长度固定(1个16进制数)所以在查找元素的时候可以按照:起始地址+n*地址长度这个公式来找,对于数组,找到元素就停止;对于列表,需要拿着地址找到元素。

二、栈

栈(stack)是一个数据集合,可以理解为只能在一端进行插入或者删除操作的列表。 栈的特点:后进先出 LIFO(last-in, first-out) 栈的概念:栈顶、栈底 栈的基本操作: 进栈(压栈):push 出栈:pop 取栈顶:gettop

1.栈的实现

使用一般的列表结构即可实现栈 进栈:li.append 出栈:li.pop 取栈顶:li[-1]

也可以封装为一个栈类 python

class Stack: #后进先出 def __init__(self): self.stack = [] #进栈 def push(self,element): self.stack.append(element) #出栈 def pop(self): if not self.is_empty: self.stack.pop() else: print('栈空!') #查看栈顶 def gettop(self): if not self.is_empty: return self.stack[-1] else: print('栈空!') #判断栈是否为空 @property def is_empty(self): return len(self.stack) == 0

2.小应用:括号匹配问题

括号匹配问题:给一个字符串,其中包含小括号、中括号、大括号,求该字符串中的括号是否匹配。 例如: ()()[]{} 匹配 ([{()}]) 匹配 []( 不匹配 [(]) 不匹配

思路分析: 括号匹配是以左括号开始,右括号结束(右括号开始的话直接认为不匹配);若为左括号,则进栈,若为右括号则出栈,操作的均为左括号;最终判断栈若为空则匹配成功。

def brace_math(s): match = {'}': '{', ']': "[", ')': '('} stack = Stack() for ch in s: if ch in ['(','<','{','[']: stack.push(ch) else: if stack.is_empty: return False elif stack.gettop() == match[ch]: stack.pop() else: return False if not stack.is_empty: return False else: return True

三、队列

队列(Queue)是一个数据集合,仅允许在列表的一端进行插入,另一端进行删除。 进行插入的一端称为队尾(rear),插入动作称为进队或入队 进行删除的一端称为队头(front),删除动作称为出队 队列的性质:先进先出(First-in, First-out)

队列不能用列表简单实现:对于出队,需要涉及到列表复位,时间复杂度比较高。

1.队列的实现

环形队列:当队尾指针rear == Maxsize - 1时,再前进一个位置就自动到0. 队首指针前进1:front = (front + 1) % MaxSize 队尾指针前进1:rear = (rear + 1) % MaxSize 队空条件:rear == front 队满条件:(rear + 1) % MaxSize == front

实现方式一:

封装一个队列类

class Queue: def __init__(self, size=100): self.queue = [0 for _ in range(size)] self.size = size self.rear = 0 # 队尾指针 self.front = 0 # 队首指针 def push(self, element): if not self.is_filled(): self.rear = (self.rear + 1) % self.size self.queue[self.rear] = element else: raise IndexError("Queue is filled.") def pop(self): if not self.is_empty(): self.front = (self.front + 1) % self.size return self.queue[self.front] else: raise IndexError("Queue is empty.") # 判断队空 def is_empty(self): return self.rear == self.front # 判断队满 def is_filled(self): return (self.rear + 1) % self.size == self.front

利用python内置模块

from collections import dequeq = deque([1,2,3,4,5], 5)q.append(6) # 队尾进队print(q.popleft()) # 队首出队# 用于双向队列q.appendleft(1) # 队首进队q.pop() # 队尾出队

2.双向队列

双向队列的两端都支持进队和出队操作 双向队列的基本操作: 队首进队 队首出队 队尾进队 队尾出队

四、迷宫问题

给一个二维列表,表示迷宫(0表示通道,1表示围墙)。给出算法,求一条走出迷宫的路径。 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]]

1.栈——深度优先搜索

回溯法 思路:从一个节点开始,任意找下一个能走的点,当找不到能走的点时,退回上一个点寻找是否有其他方向的点。 使用栈存储当前路径

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]]dirs = [ lambda x,y: (x+1,y), lambda x,y: (x-1,y), lambda x,y: (x,y-1), lambda x,y: (x,y+1)]def maze_path(x1,y1,x2,y2): stack = [] stack.append((x1, y1)) while(len(stack)>0): curNode = stack[-1] # 当前的节点 if curNode[0] == x2 and curNode[1] == y2: # 走到终点了 for p in stack: print(p) return True # x,y 四个方向 x-1,y; x+1,y; x,y-1; x,y+1 for dir in dirs: nextNode = dir(curNode[0], curNode[1]) # 如果下一个节点能走 if maze[nextNode[0]][nextNode[1]] == 0: stack.append(nextNode) maze[nextNode[0]][nextNode[1]] = 2 # 2表示为已经走过 break else: maze[curNode[0]][curNode[1]] = 2 stack.pop() else: print("没有路") return Falsemaze_path(1,1,8,8)

2.队列——广度优先搜索

from collections import dequemaze = [ [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]]dirs = [ lambda x, y: (x + 1, y), lambda x, y: (x - 1, y), lambda x, y: (x, y - 1), lambda x, y: (x, y + 1)]def print_r(path): curNode = path[-1] realpath = [] while curNode[2] != -1: realpath.append(curNode[0:2]) curNode = path[curNode[2]] realpath.append(curNode[0:2]) # 起点 realpath.reverse() for node in realpath: print(node)def maze_path_queue(x1, y1, x2, y2): queue = deque() queue.append((x1, y1, -1)) path = [] while len(queue) > 0: curNode = queue.popleft() path.append(curNode) if curNode[0] == x2 and curNode[1] == y2: # 终点 print_r(path) return True for dir in dirs: nextNode = dir(curNode[0], curNode[1]) if maze[nextNode[0]][nextNode[1]] == 0: queue.append((nextNode[0], nextNode[1], len(path) - 1)) # 后续节点进队,记录哪个节点带他来的 maze[nextNode[0]][nextNode[1]] = 2 # 标记为已经走过 else: print("没有路") return Falsemaze_path_queue(1, 1, 8, 8)

五、视频链接

迷宫问题

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:leetcode每日一题【399. 除法求值】==》并查集&模板
下一篇:python_并发编程初探(进程篇)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~