优先队列其实就是由各种堆实现,最大堆可以实现最大优先队列,最小堆可以实现最小优先队列。
可以参考以下文章:
优先队列(PriorityQueue) - 简书 (jianshu.com)
排序算法-堆排序和时间复杂度_阿巴卡的博客-CSDN博客_堆排序时间复杂度
优先队列(priority queue)_csuzhucong的博客-CSDN博客_优先队列
本文就时间复杂度进行分析:
1. 从一个无序的序列调整成最大堆(最小堆)的形式,时间复杂度为O(n),理由如下:
该调整方法是从 n 2 \frac{n}{2} 2n开始(可以证明 n 2 \frac{n}{2} 2n是从后往前看第一个非叶子结点),对每个非叶子节点进行下沉操作
某个节点进行下沉操作的时间复杂度与该节点所在的高度成正比(因为需要与它的两个孩子对比,下去之后继续跟两个孩子对比,直至到达叶子节点或者不用下去)
那么总的时间复杂度与 所有非叶子节点的高度之和 成正比
一共
h
h
h层,第
i
i
i层有
2
i
2^{i}
2i个节点,高度为
h
−
i
h-i
h−i
S
=
2
0
∗
h
+
2
1
∗
(
h
−
1
)
+
⋯
+
2
i
∗
(
h
−
i
)
+
⋯
+
2
h
−
1
∗
(
h
−
(
h
−
1
)
)
S = 2^0 * h + 2^1 * (h-1) + \cdots + 2^i * (h-i) + \cdots + 2^{h-1} * (h-(h-1))
S=20∗h+21∗(h−1)+⋯+2i∗(h−i)+⋯+2h−1∗(h−(h−1))
S = 2 S − S = 2 1 ∗ h + 2 2 ∗ ( h − 1 ) + ⋯ + 2 h − 1 ∗ ( h − ( h − 2 ) ) + 2 h ∗ ( h − ( h − 1 ) ) − S = − 2 0 ∗ h + 2 1 + ⋯ + 2 h − 1 + 2 h ∗ ( h − ( h − 1 ) ) = − h + 2 h − 2 + 2 h = 2 h + 1 − h − 2 \begin{aligned} S &= 2S - S \\ &= 2^1 *h + 2^2 * (h-1) + \cdots + 2^{h-1} * (h-(h-2)) + 2^h * (h-(h-1)) - S \\ &= -2^0 * h + 2^1 + \cdots + 2^{h-1} + 2^h * (h-(h-1)) \\ &= -h + 2^h - 2 + 2^h \\ &= 2^{h+1} - h - 2 \end{aligned} S=2S−S=21∗h+22∗(h−1)+⋯+2h−1∗(h−(h−2))+2h∗(h−(h−1))−S=−20∗h+21+⋯+2h−1+2h∗(h−(h−1))=−h+2h−2+2h=2h+1−h−2
由
2
0
+
2
1
+
⋯
+
2
h
=
n
2^0+2^1+\cdots+2^h=n
20+21+⋯+2h=n可得
h
=
l
o
g
2
(
n
+
1
)
−
1
=
O
(
l
o
g
2
n
)
h=log_2(n+1) - 1=O(log_2n)
h=log2(n+1)−1=O(log2n),所以
S
=
n
−
l
o
g
2
(
n
+
1
)
−
2
=
O
(
n
)
S=n-log_2(n+1)-2=O(n)
S=n−log2(n+1)−2=O(n)。
2. 堆排序的时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n),理由如下:
以大顶堆为例,分为两部分:
- 将无序的列表整理成最大堆形式;
- 把根节点取走,根节点存的就是最大的,用最后一层的最后一个节点代替根节点,然后从对根节点进行下沉操作。循环第2步,直到节点被全部取走。
由于对根节点的下沉操作的时间复杂度与整个堆的高度
h
h
h成正比,而高度
h
=
O
(
l
o
g
2
n
)
h=O(log_2n)
h=O(log2n),其中
n
n
n一直在变,可以发现第二部分的时间复杂度为:
S
=
l
o
g
2
n
+
l
o
g
2
(
n
−
1
)
+
⋯
+
l
o
g
2
1
=
l
o
g
2
(
n
!
)
\begin{aligned} S &= log_2 n + log_2 (n-1) + \cdots + log_2 1 \\ &= log_2 (n!) \end{aligned}
S=log2n+log2(n−1)+⋯+log21=log2(n!)
可以证明
l
o
g
2
(
n
!
)
和
n
l
o
g
2
n
log_2 (n!)和nlog_2 n
log2(n!)和nlog2n是同阶函数:
n
2
n
2
≤
n
!
≤
n
n
1
4
n
l
o
g
(
n
)
≤
n
2
l
o
g
(
n
1
2
)
≤
n
2
l
o
g
(
n
2
)
≤
n
!
≤
n
l
o
g
(
n
)
\frac{n}{2}^{\frac{n}{2}} \le n! \le n^n \\ \frac{1}{4}nlog(n) \le \frac{n}{2}log(n^{\frac{1}{2}}) \le \frac{n}{2} log(\frac{n}{2}) \le n! \le nlog(n)
2n2n≤n!≤nn41nlog(n)≤2nlog(n21)≤2nlog(2n)≤n!≤nlog(n)
所以,第二部分的时间复杂度
S
=
O
(
n
l
o
g
(
n
)
)
S=O(nlog(n))
S=O(nlog(n)),由于第一部分的时间复杂度为
O
(
n
)
O(n)
O(n),所以总的时间复杂度为
O
(
n
l
o
g
(
n
)
)
O(nlog(n))
O(nlog(n))。