数据结构(3)集合、树、图、双指针

集合set

集合是无序的,不重复的。向集合中插入1,2,则集合可能为{1,2}或者{2,1}
集合的主要作用:检查某一个元素是否存在;处理重复元素
leetcode中常见的集合有Hash set、Linklist set、Tree set…最常用的Hash set

Hashset

如何将一个元素加入到Hash set 里面去:
在这里插入图片描述

Hash set操作的时间复杂度

搜索(Search)O(1)/O(k)(有哈希冲突)
插入(Insert)O(1)/O(k)(有哈希冲突)
删除(Delete)O(1)/O(k)(有哈希冲突)

通常说O(1)就行

Python3集合常用操作

在这里插入图片描述

树Tree

树是一种由节点组成的数据结构,但它比链表更加高级,在链表中,一个节点连接着另一个节点,树也是由许多的节点构成的,唯一的区别就是一个树节点可以连接多个树节点。

在树中,每个节点都含有自己的数值,以及与之相连的子节点,连接节点的线叫做相连线(edge)。
根节点(root):一颗树只有一个根节点,根节点作为起源,由它展开一个树状的数据结构。
尾节点(或称叶子节点)(leaf node):位于树的最底部,没有任何子节点。

一个树由许许多多的子树(sub-tree)构成,每个节点加上它所有的子节点(包括子节点的子节点们)就是一个子树。

节点的高度(height),意味着此节点到尾节点之间相连线的最多数量
节点的深度(depth),意味着此节点到根节点之间相连线的最多数量

关于树的高度、深度与层这个问题,有不同的定义,可以参考下

https://blog.csdn.net/qq_36667170/article/details/84142019

树的分类

无序树:树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称为自由树;
有序树:树中任意节点的子节点之间有顺序关系,这种树称为有序树;
二叉树:每个节点最多含有两个子树的树称为二叉树;
完全二叉树:对于一颗二叉树,假设其深度为d(d>1)。除了第d层外,其它各层的节点数目均已达最大值,且第d层所有节点从左向右
连续地紧密排列,这样的二叉树被称为完全二叉树(即从树的根节点,从上到下,从左到右依次填满节点所形成的
二叉树),其中满二叉树的定义是所有叶节点都在最底层的完全二叉树;
满二叉树(Full Binary Tee):在满二叉树中,每个不是尾节点的节点都有左右两个子节点。并且所有尾节点都在同一个层上
平衡二叉树(AVL树):当且仅当任何节点的两棵子树的高度差不大于1的二叉树;
排序二叉树(二叉查找树(英语:Binary Search Tree),也称二叉搜索树、有序二叉树);
霍夫曼树(用于信息编码):带权路径最短的二叉树称为哈夫曼树或最优二叉树;
B树:一种对读写操作进行优化的自平衡的二叉查找树,能够保持数据有序,拥有多余两个子树。

下图左边是满二叉树,也是完全二叉树。右边只是完全二叉树。下边不是满二叉树更不是完全二叉树
在这里插入图片描述
下图不是满二叉树,因为满二叉树要求所有叶子节点在同一个层上
在这里插入图片描述
下图不是完全二叉树,因为要从上到下,从左到右一次填满
在这里插入图片描述
下图是完全二叉树
在这里插入图片描述

二叉树的遍历

树的遍历是树的一种重要的运算。所谓遍历是指对树中所有结点的信息的访问,即依次对树中每个结点访问一次且仅访问一次,我们把这种对所有节点的访问称为遍历(traversal)。那么树的两种重要的遍历模式是深度优先遍历和广度优先遍历,深度优先一般用递归,广度优先一般用队列。一般情况下能用递归实现的算法大部分也能用堆栈来实现。

不像数组,在树中我们无法随时获取任意节点,遍历树总是从根节点开始,以下是常见的三种遍历树的方式(深度优先遍历):

前序遍历 (Pre-order Traversal):先访问节点,然后访问子树,最后再访问子树,对于每个节点迭代此操作
中序遍历 (In-order Traversal):先访问子树上的节点,再访问节点,最后再访问子树上的节点
后序遍历 (Post-order Traversal):先访问子树,然后访问子树,最后再访问节点

在这里插入图片描述
在这里插入图片描述

堆Heap

堆是完全二叉树,且堆的所有节点值都全部小于等于它的孩子节点值(最小堆),或者全部大于等于它的孩子节点值(最大堆)
在这里插入图片描述

在这里插入图片描述

堆操作的时间复杂度

搜索(Search)O(1) 一般堆里的搜索只搜索堆顶元素。若搜索堆中人一个元素,则为O(N)
插入(Insert)O(logN)
删除(Delete)O(logN)一般是删除堆顶元素

最大堆为例:

在任何的时间点,最大堆都应该保持其特性:父节点的数值比所有子节点大。在插入新元素的时候,我们要遵循以下的步骤:
1在堆的最后新建一个节点。
2将数值赋予新节点。
3将其节点和父节点比较。
4如果新节点的数值比父节点大,调换父子节点的位置。
5重复步骤3和4直到最大堆的特性被满足。

以下是删除根节点的步骤:
1移除根节点
2将最后的元素移到根节点处
3将子节点和父节点比较
4如果父节点的数值比子节点小,替换父子节点
5重复步骤3和4直到最大堆的特性被满足。

堆初始化与插入成堆操作

**堆初始化:**将一组无序的数,先变成完全二叉树,然后将完全二叉树变成最大堆或者最小堆。时间复杂度为O(N)  
将一个无序数组变成完全二叉树,其结构是唯一的:
在这里插入图片描述
每个节点只与它的孩子节点进行比较,若比孩子节点大,就与最小的孩子节点进行交换。叶子节点没有孩子节点因此不用管它。
7和5交换——9比12,16小,不交换——10和5交换——10和7交换
在这里插入图片描述
从完全二叉树转化成最小堆的操作时间复杂度也是O(N):
高度为0 的这层:对最多有(n+1)/2个节点,这些节点都没有孩子,因此交换次数为0
高度为1 的这层:对最多有((n+1)/2)*1/2=(n+1)/4个节点,每个节点最多交换1次。
高度为1 的这层:对最多有(n+1)/4)*1/2=(n+1)/8个节点,每个节点最多交换2次。(如10 与5交换,10与7交换)
高度为 i 的这层:对最多有(n+1)/2i+1个节点,每个节点最多交换 i 次。
总的交换次数为:图中n应为n+1
在这里插入图片描述在这里插入图片描述
因此时间复杂度是O(N)。 
从数组变成完全二叉树和从完全二叉树变到最大堆最小堆的时间复杂度都是O(N),并且两个步骤不是嵌套的,因此取最大的时间复杂度作为整体的时间复杂度,即O(N)。

插入成堆的时间复杂度为 O(N Log N):

Python3堆常用操作

图中是最小堆的创建方法。关于最大堆,python中没有方法可以帮你创建最大堆,若想将一个列表转为最大堆,则先将列表的所有元素都乘以-1,然后用以下的办法先创建最小堆,最后再乘以-1就能实现最大堆了。
最小堆:
导入heapq库。先创建一个列表,然后应用heapq.heapify()进行堆化。heapq.heappush()加入元素,最后是这样:
在这里插入图片描述
heappop()删除堆顶元素,同时提拔一个堆顶元素
len()可以用来查看堆是否为空
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值