数据结构的分类
- 线性结构:数据结构中的元素存在一对一的相互关系
- 树结构:数据结构中的元素存在一堆多的先相关系
- 图机构:数据结构中的元素存在多对多的相互关系;例如:地图
列表
1.列表在内存中是顺序存储的(顺序表)
2.数组与列表有两个不同点:
- 数组类型要相同
- 数组长度固定
3.列表中的操作时间复杂度:
新增:O(1)
插入和删除:O(n)
4.在python中列表的实现是把地址存储在列表中
栈
- 栈(stack)是一个数据集合,可以理解为只能在一段进行插入或删除操作的列表。
- 栈的特点:先进后出LIFO(last-in,first-out)
- 栈的概念:栈顶、栈低
- 栈的基本操作:进栈:push;出栈:pop;取栈顶:gettop
- 栈在系统底层常用。
- 在python中使用一般的列表结构即可实现栈
进栈:li.append
出栈:li.pop
取栈顶:li[-1]
![f5c14a70caa8c4bf1aed2ad2c4760c0c.png](https://i-blog.csdnimg.cn/blog_migrate/5af5e3fa64d8753fc4f90e6ba709c853.png)
栈的应用:括号匹配问题
括号匹配问题:给一字符串,其中包含小括号、中括号、大括号,求该字符串的符号是否匹配。
例:
() () [ ] { } 匹配
( [ { ( ) } ]) 匹配
[ ] ( 不匹配
[ ( ] ) 不匹配
![70f393d78dd92d75db27b5ab2c05c3ae.png](https://i-blog.csdnimg.cn/blog_migrate/83484a8364a6f1b643c47d2d5729c76d.png)
栈的实现
![cab86793fada78fc08dd3a3b1b3ed4d9.png](https://i-blog.csdnimg.cn/blog_migrate/ba557a943a05461658a826434287157f.png)
队列
- 队列(Queue)是一个数据集合,仅允许在列表的一段进行插入,另一端进行删除。
- 进行插入的一段称为队尾(rear),插入动作称为进队或入队。
- 进行删除的一端称为队头(front),删除动作称为出队。
- 队列的性质先进先出(first-in,firt-out)
![e5d4a6fe7a368fe4f2ae0993c656679a.png](https://i-blog.csdnimg.cn/blog_migrate/9c8386ee340f81c520cc4ae5ad90de4a.png)
队列的实现方式——环形队列
- 环形队列:当队尾指针front==Maxsize-1时,再前进一个位置就自动到0。
- 队首指针前进1:front=(front+1)%Maxsize
- 队尾指针前进1:rear=(rear+1)%Maxsize
- 队空条件:rear==front
- 队满条件:(rear+1)%Maxsize==front
- 用pthon实现建队:
![e0af1ed2a964437d2f324b2a14599575.png](https://i-blog.csdnimg.cn/blog_migrate/7a83e1f3d718f420ff109499884b6f17.jpeg)
双向队列
双向队列的两端都支持进队和出队操作
双向队列的基本操作:队首进队、队首出队、队尾进队、队尾出队
![8660119282731cfd12a2756d4d1a0710.png](https://i-blog.csdnimg.cn/blog_migrate/438a42635bb160468df28826b2a5fd91.png)
Python中队列的内置模块
使用方法:from collections import deque
创建队列:queue=deque()
进队:append()
出队:popleft()
双向队列队首进栈:appendleft()
双向队列队尾进栈:pop()
![ae7431a3b12d4463b839674fc5660783.png](https://i-blog.csdnimg.cn/blog_migrate/63e849b313f07960c7ac6b21ddd83533.png)
队列的应用——读取文件后几行
![c012cd4c1e61e6573cf4c63ae92f5da4.png](https://i-blog.csdnimg.cn/blog_migrate/4ed2552a6c2c9715590df23b1e1a2897.png)
栈和队列的应用——迷宫问题
给一个二维列表,表示迷宫(0表示通道,1表示围墙)。给出算法,求一条走出迷宫的路径。
栈——深度优先搜索
回溯法
思路:从一个节点开始,任意找下一个能走的点,当找不到能走的点时,退回上一个点寻找是否有其他方向的点
使用栈存储当前路径
![891f025ecc0f06b487ecf4174b418734.png](https://i-blog.csdnimg.cn/blog_migrate/4ca62edf61f8749a09023f785d8dd820.png)
![57c43e5239d858739f952fbea2bb6fb8.png](https://i-blog.csdnimg.cn/blog_migrate/5e9f461d745924da76a193f9e7723761.png)
使用队列解决迷宫问题
广度优先搜索
思路:从一个节点开始,寻找接下来所有能继续走的点,继续不断寻找,直到找到出口。
使用队列存储当前正在考虑的节点
![d2580c685473b5582ac2bb7eb786eef0.png](https://i-blog.csdnimg.cn/blog_migrate/51868d5c288ab89a546964778b73e552.png)
![bed42d7cce0f65c1d0114f353cb78528.png](https://i-blog.csdnimg.cn/blog_migrate/bb2fe4bead7f0b14f1a6af77d8f9d699.jpeg)
![91c96dbaced16ec532393cbd4c8622ce.png](https://i-blog.csdnimg.cn/blog_migrate/884a9e298eeb52ec7d8dd007e2c8cb51.png)
链表
链表是一个由一系列节点组成的元素集合。每个节点包含两部分,数据域item和指向下一个节点的指针next。通过节点之间的相互连接,最终串联成一个链表。
![a6b40693f66bed23aec058d5467e5006.png](https://i-blog.csdnimg.cn/blog_migrate/bb05380fa7e0e70f6eadcf2ae3670456.jpeg)
![b3805ff535eb3e75a390d4b986337c56.png](https://i-blog.csdnimg.cn/blog_migrate/f5d902b79590831e6fe38d203ba53623.png)
头插法
![42fb55b2aba50161ea2ee55c34c9f0e4.png](https://i-blog.csdnimg.cn/blog_migrate/48c6c055753c9e0fe50c88b1690db22d.png)
尾插法
![e97f8b69542d03e06a242b424487cc06.png](https://i-blog.csdnimg.cn/blog_migrate/e6e2e4815b011612ba6a59c182c2f4f6.png)
链表节点的插入
p.next=Node.next
Node.next=p
链表节点的删除
P=Node.next
Node.next=Node.next.next
del p
双链表
双链表的每个节点有两个指针:一个指向后一个节点,另一个指向前一个节点。
双链表的创建:
class Node(object):
def __init__(self,item=none):
self.item=item
self.next=next
self.prior=none
双链表节点的插入
p.next=Node.next
Node.next=p
p.prior=Node
Node.next=p
双链表节点的删除
P=Node.next
Node.next=p.next
p.next.prior=Node
del p
链表在插入和删除的操作上明显快于顺序表
链表的内存可以更灵活的分配(可以试着用链表重新实现栈和队列)
链表这种链式存储的数据结构对树和图的结构有很大的启发性
哈希表
哈希表是一个通过哈希函数来计算数据存储位置的数据结构,通常支持如下命令:
- insert(key,value):插入键值对(key,value)
- get(key):如果存在键为key的键值对则返回其value,否则返回空值。
- delete(key):删除键和key的键值对。
哈希表(HashTable,又称为散列表),是一种线性表的存储结构。哈希表由一个直接寻址表和一个哈希函数组成,哈希函数h(k)将元素关键字k作为自变量,返回元素的存储下标。
由于哈希表的大小是有限的,而要存储的值的总数量是无限的,因次对于任何哈希函数都会出现两个不同的元素映射到同一个位置上的情况,这种情况叫做哈希冲突。
解决哈希冲突——开放寻址法
开放寻址法:如果哈希函数返回的位置上已经有值,则可以向后探查新的位置来存储这个值。
线性探查:如果位置i被占用,则探查i+1,i+2,………
二次探查:如果位置i被占用,则探查i+12,i-12,i+22,i-22………
二度哈希:有n个哈希函数
创建哈希表
![b9d4c20569bc481915c33a6a6de34fb5.png](https://i-blog.csdnimg.cn/blog_migrate/a7e70fa1fb489b069db729e2089a2430.jpeg)
![ba1c485f7686409905d757724db91bd5.png](https://i-blog.csdnimg.cn/blog_migrate/197c0feaa6b50066ad48a6232ce1a72a.png)
![90732e434ed443dc19dbc66e3fe29066.png](https://i-blog.csdnimg.cn/blog_migrate/7a368995c1a327014e5392e8a09d4a66.png)
二叉搜索树
平均情况下,二叉搜索树进行搜索的时间复杂度为O(lgn)
最坏情况下,二叉搜索树可能会偏斜
解决方案:随机化插入
AVL树:
AVL树是一颗自动平衡的二叉搜索树。
AVL树具有以下性质:
- 根的左右子树的高度之差的绝对值不能超过1
- 根的左右子树都是平衡二叉树
插入一个节点可能就会破坏AVL树的平衡,可以通过旋转操作来进行修正
插入一个节点后,只有从插入节点到根节点的路径上的节点的平衡可能被改变,我们需要找到第第一破坏了平衡条件的节点,称之为K。K的两颗子树的高度差2
不平衡的出现情况可能有4种情况
- 不平衡是由于对K的右孩子的右子树插入导致的:左旋
- 不平衡是由于对K的左孩子的左子树插入导致的:左旋
- 不平衡是由于对K的右孩子的左子树插入导致的:右旋—左旋
- 不平衡是由于对K的左孩子的右子树插入导致的:左旋—右旋
B树(B-Tree):B树是一颗自平衡的多路径搜索树。常用于数据库的索引。