DataStructure
Posted bubu99
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DataStructure相关的知识,希望对你有一定的参考价值。
数据结构
- 数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。
- 简单来说,数据结构就是设计数据以何种方式组织并存储在计算机中。
- 比如:列表、集合与字典等都是一种数据结构。
- N.Wirth: “程序=数据结构+算法”
分类
数据结构按照其逻辑结构可分为线性结构、树结构、图结构
- 线性结构:数据结构中的元素存在一对一的相互关系
- 树结构:数据结构中的元素存在一对多的相互关系
- 图结构:数据结构中的元素存在多对多的相互关系
一、列表/数组
- 内容:列表在内存中以一块连续的空间存放,列表中存放的是每个元素的引用
- 基本操作:
- 新增:insert O(n),append O(1)
- 删除:remove O(n),pop O(1)
- 修改:O(1)
- 遍历:O(n)
- 查找:O(n)
二、栈
- 内容:栈(Stack)是一个数据集合,可以理解为只能在一端进行插入或删除操作的列表。
- 特点:后进先出(last-in, first-out)
- 其他概念:栈顶 栈底
- 基本操作:
- 进栈:push
- 出栈:pop
- 取栈顶元素:gettop
- 实现原理:
- 不需要自己定义,使用列表结构即可。
- 进栈函数:append
- 出栈函数:pop
- 查看栈顶函数:li[-1]
- 栈的应用:
- 括号匹配问题,给一个字符串中,其中包含(,[,{ 判断该字符串中的括号是否匹配.例 ()()[]{} √,([{()}]) √,[]( X,[(]) X
- 思路:循环字符串,创建一个空栈,如果字符串中游匹配的字符,放入栈中,如果找到相匹配的括号,将这对括号出栈
三、队列
- 内容:
- 队列(Queue)是一个数据集合,仅允许在列表的一端进行插入,另一端进行删除。
- 进行插入的一端称为队尾(rear),插入动作称为进队或入队
- 进行删除的一端称为队头(front),删除动作称为出队
- 特点:先进先出(First-in, First-out)
- 双向队列:
- 队列的两端都允许进行进队和出队操作。
- 使用方法: from collections import deque
- 创建队列: queue = deque()
- 进队:append
- 出队:popleft
- 双向队列队首进队:appendleft
- 双向队列队尾进队:pop
- 实现原理(列表+指针):
- 初步设想:列表+两个下标指针
- 实现:创建一个列表和两个变量,front指向队首,rear指向队尾,初始都为0
- 进队操作:元素写到li[rear]的位置,rear自增1
- 出队操作:返回li[front]的位置,front自减1
- 实现原理(环形队列):
- 环形队列:当队尾指针front == Maxsize + 1时,再前进一个位置就自动到0。
- 实现方式:求余数运算
- 队首指针前进1:front = (front + 1) % MaxSize
- 队尾指针前进1:rear = (rear + 1) % MaxSize
- 队空条件:rear == front 队满条件:(rear + 1) % MaxSize == front
迷宫问题
方法1:使用栈
思路:从上一个节点开始,任意找下一个能走的节点,当找到不能走的节点时,退回到上一个节点,寻找是否有其他方向的点
方法:创建一个栈,首先将入口的位置进栈,当栈不空时候循环,获取栈顶元素,寻找下一个可走的相邻方块,如果找不到可走的相邻方块,说明当前是死路,进行回溯(将当前的点出栈,查看前面的点是否还有其他出路),体现深度优先的思想
方法2:使用队列
思路:从一个节点开始寻找,寻找下面能继续走的点,继续寻找直到能找出出口
方法:创建一个空队列,将起点位置入队,在队列不空时循环,出队一次,如果相邻的位置为出口,则结束.否则找出4个相邻方块中可走的方块,全部入队,体现广度优先的思想
约瑟夫问题
n个人围成一个圈,每个人分别标注为1、2、...、n,要求从1号从1开始报数,报到k的人出圈,接着下一个人又从1开始报数,如此循环,直到只剩最后一个人时,该人即为胜利者。例如当n=10,k=4时,依次出列的人分别为4、8、2、7、3、10,9、1、6、5,则5号位置的人为胜利者。给定n个人,请你编程计算出最后胜利者标号数。
- 时间复杂度: 第1种列表法的时间复杂度是O(n2).第2种链表法的时间复杂度是O(nm)
- 如果n大于m时,链表法优于列表法,n小于m时,列表法优于链表法
#n表示总人数,m表示报到的数 def yuesefu_1(n,m): #1.将所有元素放进列表中,并定义初始的下标为0 people = [i for i in range(1,n+1)] x = 0 #2.在列表不空的时候循环 while len(people) > 0: #3.计算报数的人的下标, # 1,2,3,4,5,6,7,8 报数 # 0,1,2,3,4,5,6,7 下标,每次取出对总人数的余数就是要找的人 dead_location = (x+(m-1))%len(people) yield people.pop(dead_location) #将找到的人移除出列表 x = dead_location #从移除出去的人的位置上,继续执行 print(list(yuesefu_1(9,4)))
class LinkList: #自定义链表实现类 class Node: def __init__(self,item=None): self.item = item self.next = None class LinkListIterator: def __init__(self,node): self.node = node def __next__(self): if self.node: cur_node = self.node self.node = cur_node.next return cur_node.item def __iter__(self): return self def __init__(self,iteratbe=None): self.head = LinkList.Node(0) self.tail = self.head self.extend(iteratbe) #链表添加 def append(self,obj): s = LinkList.Node(obj) self.tail.next = s self.tail = s #链表扩展 def extend(self,iterable): for obj in iterable: self.append(obj) self.head.item += len(iterable) def remove_nth_node(self,node,m): #删除链表第n个元素 for i in range(m-2): node = node.next p = node.next node.next = p.next self.head.item -= 1 return p def __iter__(self): return self.LinkListIterator(self.head.next) def __len__(self): return self.head.item def __str__(self): return ‘<<‘+", ".join(map(str,self)) +">>" def yuesefu_link(n,m): people = LinkList([i for i in range(1,n+1)]) people.tail.next = people.head.next x = people.head.next while len(people)>0: p = people.remove_nth_node(x,m) x = p.next yield p.item print(list(yuesefu_link(9,4)))
以上是关于DataStructure的主要内容,如果未能解决你的问题,请参考以下文章
[DataStructure]线性数据结构之稀疏数组链表栈和队列 Java 代码实现
DataStructure--Tree--decision tree 决策树
[DataStructure]非线性数据结构之哈希表二叉树及多叉树 Java 代码实现
Software-DataStructure 三年一直迷糊的链表