已发布·持续改进
树与堆 指南 · 3/6
本章目前仅提供英文版。
We build BST insert and search plus a min-heap in Python, then port the min-heap to C++, Java and TypeScript.
class Node:
def __init__(self, key):
self.key, self.left, self.right = key, None, None
class BST:
def __init__(self):
self.root = None
def insert(self, key):
if self.root is None:
self.root = Node(key)
return
cur = self.root
while True:
if key == cur.key:
return # ignore duplicates
side = "left" if key < cur.key else "right"
nxt = getattr(cur, side)
if nxt is None:
setattr(cur, side, Node(key))
return
cur = nxt
def contains(self, key):
cur = self.root
while cur is not None and cur.key != key:
cur = cur.left if key < cur.key else cur.right
return cur is not None
t = BST()
for k in [50, 30, 70, 20, 40]:
t.insert(k)
print(t.contains(40), t.contains(45)) # True Falseside picks a child; an empty slot gets the new node, otherwise we move down.class MinHeap:
def __init__(self, items=()):
self.a = list(items)
for i in range(len(self.a) // 2 - 1, -1, -1): # heapify, O(n)
self._down(i)
def push(self, x):
self.a.append(x)
self._up(len(self.a) - 1)
def peek(self):
return self.a[0]
def pop(self):
a = self.a
top, last = a[0], a.pop() # IndexError when empty
if a:
a[0] = last
self._down(0)
return top
def _up(self, i):
a = self.a
while i > 0 and a[i] < a[(i - 1) // 2]:
p = (i - 1) // 2
a[i], a[p] = a[p], a[i]
i = p
def _down(self, i):
a, n = self.a, len(self.a)
while (c := 2 * i + 1) < n:
if c + 1 < n and a[c + 1] < a[c]:
c += 1 # the smaller child
if a[i] <= a[c]:
break
a[i], a[c] = a[c], a[i]
i = c
def __len__(self):
return len(self.a)
h = MinHeap([9, 5, 7, 1, 3, 2])
h.push(4)
print([h.pop() for _ in range(len(h))]) # [1, 2, 3, 4, 5, 7, 9]_up climbs while smaller than the parent (i - 1) // 2.pop moves the last item to the root, then calls _down._down runs while a left child 2 * i + 1 exists and swaps with the smaller child.#include <iostream>
#include <utility>
#include <vector>
class MinHeap {
std::vector<int> a;
public:
void push(int x) {
a.push_back(x);
std::size_t i = a.size() - 1;
while (i > 0 && a[i] < a[(i - 1) / 2]) {
std::swap(a[i], a[(i - 1) / 2]);
i = (i - 1) / 2;
}
}
int pop() { // call only when not empty
int top = a.front();
a.front() = a.back();
a.pop_back();
std::size_t i = 0, n = a.size();
while (2 * i + 1 < n) {
std::size_t c = 2 * i + 1;
if (c + 1 < n && a[c + 1] < a[c]) ++c;
if (a[i] <= a[c]) break;
std::swap(a[i], a[c]);
i = c;
}
return top;
}
bool empty() const { return a.empty(); }
};
int main() {
MinHeap h;
for (int x : {5, 3, 8, 1, 9, 2}) h.push(x);
while (!h.empty()) std::cout << h.pop() << ' '; // 1 2 3 5 8 9
}import java.util.ArrayList;
public class MinHeap {
private final ArrayList<Integer> a = new ArrayList<>();
public void push(int x) {
a.add(x);
int i = a.size() - 1;
while (i > 0 && a.get(i) < a.get((i - 1) / 2)) {
swap(i, (i - 1) / 2);
i = (i - 1) / 2;
}
}
public int pop() {
int top = a.get(0);
int last = a.remove(a.size() - 1);
if (!a.isEmpty()) {
a.set(0, last);
int i = 0, n = a.size();
while (2 * i + 1 < n) {
int c = 2 * i + 1;
if (c + 1 < n && a.get(c + 1) < a.get(c)) c++;
if (a.get(i) <= a.get(c)) break;
swap(i, c);
i = c;
}
}
return top;
}
public boolean isEmpty() { return a.isEmpty(); }
private void swap(int i, int j) { a.set(i, a.set(j, a.get(i))); }
public static void main(String[] args) {
MinHeap h = new MinHeap();
for (int x : new int[] {5, 3, 8, 1, 9, 2}) h.push(x);
while (!h.isEmpty()) System.out.print(h.pop() + " ");
}
}a.set returns the old value, so swap fits on one line.
class MinHeap {
private a: number[] = [];
push(x: number): void {
const a = this.a;
a.push(x);
let i = a.length - 1;
while (i > 0 && a[i] < a[(i - 1) >> 1]) {
const p = (i - 1) >> 1;
[a[i], a[p]] = [a[p], a[i]];
i = p;
}
}
pop(): number | undefined {
const a = this.a;
const top = a[0];
const last = a.pop();
if (a.length > 0 && last !== undefined) {
a[0] = last;
let i = 0;
while (2 * i + 1 < a.length) {
let c = 2 * i + 1;
if (c + 1 < a.length && a[c + 1] < a[c]) c++;
if (a[i] <= a[c]) break;
[a[i], a[c]] = [a[c], a[i]];
i = c;
}
}
return top;
}
get size(): number { return this.a.length; }
}
const h = new MinHeap();
[5, 3, 8, 1, 9, 2].forEach((x) => h.push(x));
while (h.size > 0) console.log(h.pop()); // 1 2 3 5 8 9BST insert and search walk down one level per step, and a min-heap needs only an array, two index formulas, sift up and sift down. In production code use heapq, std::priority_queue or PriorityQueue; the real-world chapter covers their default orders and pitfalls.
0 条评论
登录 · 登录后即可发表评论。
来发表第一条评论吧。