1.优先级队列
1.1 概念
队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,一般出队列时,可能需要优先级高的元素先出队列。该中场景下,使用队列显然不合适,比如:初中那会班主任排座位时可能会让成绩好的同学先挑座位。
这种情况下,数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。
优先级队列:入队一样,默认从队尾入队,出队的时候按照优先级出队
优先级相同的元素按照FIFO出队,优先级高的元素首先出队。
优先级队列的两大特点:逻辑结构,不是具体的物理结构
1.元素个数动态变化
2.按照优先级出队 优先级高的元素首先出队
优先级队列这个数据结构可以使用排序数组来替代?
但是元素是无时无刻不在动态变化,出队的那一刻要进行元素的优先级排序。无时无刻不再变化的动态数据结构。
数组排序(按照优先级排序)后输出有区别吗?
第一:优先级队列不等同于排序数组。
第二:数组排序之后元素是固定的。
2.优先级队列的模拟实现
JDK1.8中的PriorityQueue底层使用了堆这种数据结构。(优先级队列背后的数据结构---堆)
2.1 堆的概念
如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储 在一 个一维数组中,并满足:Ki = K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为小堆(或大 堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
堆的性质:元素依次从上至下,从左至右进行排列
1.堆中某个节点的值总是不大于或不小于其父节点的值;
2.堆是一棵完全二叉树,一般使用动态数组(不用存储null节点,元素都靠左排列)存储具体元素。
2.2 堆的存储方式
结构上:堆是一颗完全二叉树。每一层节点都靠左排列,常用数组来存储完全二叉树。
关于完全二叉树的节点编号:根据编号以及索引关系,在数组中寻找某一节点的子节点与父节点。
编号和索引保持一致,都从0开始编号,若某个节点的编号(索引)为x;
性质1.判断父节点
如何判断父节点是否存在,若存在,索引是 ==> parent(x) = (x-1) / 2
x > 0,则一定存在父节点(在二叉树中,只有根节点【根节点索引为0】没有父节点),且父节点的编号为(x-1) / 2
性质2.判断左子树节点
如何判断当前节点x还存在于左子树节点?左子树节点编号是多少?
当前完全二叉树的节点个数 <= 数组最大长度
左子树节点编号为 2x + 1 < size(当前数组中有效的元素个数)
性质3.判断右子树节点
右子树节点编号为 2x + 2 < size