Algs4-2.4.24链接实现优先队列
2.4.24使用链接的优先队列。用堆有序的二叉树实现一个优先队列,但使用链表结构代替数组。每个结点都需要三个链接:两个向下,一个向上。你的实现即使在无法预知队列大小的情况下也能保证优先队列的基本操作所需的时间为对数级别。
答:
按照正文中用数组来表示堆时元素个数N,对于插入新元素需要放置的位置和删除最大元素需要移动尾元素都是一个很好的位置指示器。使用链接来表示堆时,也需一个类似这样的位置指示器,这是使用链接来实现优先队列的关键所在。
使用一个双向队列,用来存放还可以作为父结点的结点,在队头存放即将要作为父结点的结点,那么在队尾放置最后可以作为父结点的结点。
以下是算法的要点描述:
1)插入新结点时,
1.1)如果此时堆中只有这一个结点,那么不需要为新结点指定父结点。将新结点从双向队列的队尾入队。
1.2)插入新结点时,如果此时堆中已有其他结点,那么将双向队列队头的结点作为新结点的父结点,将新结点从双向队列的队尾入队。
1.2.1)如果父结点没有左孩子,
那么父结点的左孩子指向新结点。
新结点进行swim(),swim时的交换是结点中的item属性值,不是改变结点的父子关系指向。
1.2.2)如果父结点没有右孩子,
那么父结点的右孩子指向新结点。
父结点从双向队列的队头出队。
新结点swim()。
2)删除时
2.1)如果已经没有结点了不处理。
2.2)如果只有一个结点了,返回它。
2.3)如果还有多个结点
双向队列队尾元素出队,将其作为尾结点。
如果尾结点是其父结点的右孩子,那么将其父结点从双向队列的队头入队。(因为这个父结点可以作为下一个新结点的父结点了)
交换顶点与尾结点item属性值。
解除尾结点与其父结点的父子关系(尾结点是左孩子时清空父结点的左指向,尾结点是右孩子时清空父结点的右指向,清空尾结点的父指向)
顶点sink(),sink中的交换只交换结点的item属性值。
返回顶点。