Skip to content

Commit 1006c6f

Browse files
Create 手写堆.md
1 parent 8baee49 commit 1006c6f

File tree

2 files changed

+169
-73
lines changed

2 files changed

+169
-73
lines changed

Heap/手写堆.md

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
2+
3+
# 小顶堆(Go)
4+
5+
建堆有两种方式:
6+
7+
1. 自顶向下,从第一个节点开始到最后一个节点遍历,按插入节点的方式建堆,节点的交换是从下往上的,时间复杂度是 `O(nlogn)`
8+
2. 自底向上,从倒数第一个非叶子节点开始,到第一个节点,节点的交换是从上往下的,时间复杂度是 `O(n)`
9+
10+
堆的操作:
11+
12+
1. 插入节点:将节点插入到数组尾,用将数组的尾节点从下往上的交换方式一直往上交换
13+
14+
2. 弹出堆顶:交换堆顶节点和数组最后一个节点,删除数组最后一个节点,接着将堆顶节点用从上往下的方式一直往下交换
15+
16+
```go
17+
package main
18+
19+
import "fmt"
20+
21+
func main() {
22+
h := heap{4, 6, 9, 1, 2, 3, 12, 34, 5, 6}
23+
h.init1()
24+
fmt.Println(h)
25+
h.insert(0)
26+
fmt.Println(h)
27+
h.pop()
28+
fmt.Println(h)
29+
}
30+
31+
type heap []int
32+
33+
func (h heap) swap(i, j int) {
34+
h[i], h[j] = h[j], h[i]
35+
}
36+
37+
func (h heap) init1() { // bottom-up, O(n), 自底向上的建堆方式,节点的交换是从上往下的
38+
for i := len(h)/2 - 1; i >= 0; i-- {
39+
h.topDown(i)
40+
}
41+
}
42+
43+
func (h heap) init2() { // top-down O(nlogn) 自顶向下的建堆方式,节点的交换是从下往上的
44+
for i := 0; i < len(h); i++ {
45+
h.bottomUp(i)
46+
}
47+
}
48+
49+
func (h *heap) insert(val int) {
50+
*h = append(*h, val)
51+
h.bottomUp(len(*h) - 1)
52+
}
53+
54+
func (h heap) bottomUp(cur int) {
55+
parent := (cur+1)/2 - 1
56+
for parent >= 0 {
57+
if h[cur] < h[parent] {
58+
h.swap(cur, parent)
59+
} else {
60+
break
61+
}
62+
cur = parent
63+
parent = (parent+1)/2 - 1
64+
}
65+
}
66+
67+
func (h heap) topDown(cur int) {
68+
minn := 2*cur + 1
69+
for minn < len(h) {
70+
if 2*cur+2 < len(h) && h[2*cur+2] < h[minn] {
71+
minn = 2*cur + 2
72+
}
73+
if h[cur] > h[minn] {
74+
h.swap(cur, minn)
75+
} else {
76+
break
77+
}
78+
cur = minn
79+
minn = 2*cur + 1
80+
}
81+
}
82+
83+
func (h *heap) pop() int {
84+
h.swap(0, len(*h)-1)
85+
res := (*h)[len(*h)-1]
86+
*h = (*h)[:len(*h)-1]
87+
h.topDown(0)
88+
return res
89+
}
90+
91+
```
92+
93+
94+
95+
96+
97+
# 大顶堆(Java)
98+
99+
从第一个非叶子节点(若数组长度为 `size`,那么第一个非叶子节点的下标则为 `size / 2` )倒序遍历至第一个节点,每个循环中都与自身子节点中较大的子节点交换。
100+
101+
```java
102+
package src.DataStructure;
103+
104+
public class Heap {
105+
106+
private int[] arrays = new int[1000];
107+
108+
private int size;
109+
110+
public Heap(int[] arrays){
111+
this.size = arrays.length;
112+
System.arraycopy(arrays, 0, this.arrays, 0, size);
113+
heapify(size);
114+
}
115+
116+
public void add(int value){
117+
arrays[size++] = value;
118+
heapify(size);
119+
}
120+
121+
122+
public void heapify(int size){
123+
for(int i = size / 2; i >= 0; i--){
124+
sink(i);
125+
}
126+
}
127+
128+
public void sink(int index){
129+
while(2 * index + 1 < size){
130+
int temp = 2 * index + 1;
131+
if(temp + 1 < size && arrays[temp] < arrays[temp + 1]){
132+
temp = temp + 1;
133+
}
134+
if(arrays[temp] <= arrays[index]){
135+
break;
136+
}
137+
swap(arrays, index, temp);
138+
index = temp;
139+
}
140+
}
141+
142+
public int poll(){
143+
int ans = arrays[0];
144+
swap(arrays, 0, --size);
145+
heapify(size);
146+
return ans;
147+
}
148+
149+
public void swap(int[] nums, int left, int right){
150+
int temp = nums[left];
151+
nums[left] = nums[right];
152+
nums[right] = temp;
153+
}
154+
155+
156+
public static void main(String[] args) {
157+
int[] arrays = new int[]{6, 8, 10, 2, 4, 11, 13, 9, 1, 5, 7, 3};
158+
Heap heap = new Heap(arrays);
159+
heap.add(200);
160+
while(heap.size != 0){
161+
System.out.println(heap.poll());
162+
}
163+
}
164+
}
165+
166+
```
167+
168+
169+

Heap/手写大顶堆.md

Lines changed: 0 additions & 73 deletions
This file was deleted.

0 commit comments

Comments
 (0)