Optimize arrToTree function

in java, cpp, py, go, js, ts.
pull/217/head
Yudong Jin 2 years ago
parent c411969bd1
commit dcc3b2e35b

4
.gitignore vendored

@ -14,5 +14,5 @@ docs/overrides/
# python files # python files
__pycache__ __pycache__
# iml # in-progress articles
hello-algo.iml docs/chapter_heap

@ -30,8 +30,7 @@ vector<int> hierOrder(TreeNode* root) {
int main() { int main() {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
TreeNode* root = vecToTree(vector<int> TreeNode* root = vecToTree(vector<int> { 1, 2, 3, 4, 5, 6, 7 });
{ 1, 2, 3, 4, 5, 6, 7, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX });
cout << endl << "初始化二叉树\n" << endl; cout << endl << "初始化二叉树\n" << endl;
PrintUtil::printTree(root); PrintUtil::printTree(root);

@ -41,8 +41,7 @@ void postOrder(TreeNode* root) {
int main() { int main() {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
TreeNode* root = vecToTree(vector<int> TreeNode* root = vecToTree(vector<int> { 1, 2, 3, 4, 5, 6, 7 });
{ 1, 2, 3, 4, 5, 6, 7, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX});
cout << endl << "初始化二叉树\n" << endl; cout << endl << "初始化二叉树\n" << endl;
PrintUtil::printTree(root); PrintUtil::printTree(root);

@ -27,23 +27,24 @@ struct TreeNode {
* @return TreeNode* * @return TreeNode*
*/ */
TreeNode *vecToTree(vector<int> list) { TreeNode *vecToTree(vector<int> list) {
if (list.empty()) { if (list.empty())
return nullptr; return nullptr;
}
auto *root = new TreeNode(list[0]); auto *root = new TreeNode(list[0]);
queue<TreeNode *> que; queue<TreeNode *> que;
size_t n = list.size(), index = 1; que.emplace(root);
while (index < n) { size_t n = list.size(), index = 0;
while (!que.empty()) {
auto node = que.front(); auto node = que.front();
que.pop(); que.pop();
if (++index >= n) break;
if (index < n) { if (index < n) {
node->left = new TreeNode(list[index++]); node->left = new TreeNode(list[index]);
que.emplace(node->left); que.emplace(node->left);
} }
if (++index >= n) break;
if (index < n) { if (index < n) {
node->right = new TreeNode(list[index++]); node->right = new TreeNode(list[index]);
que.emplace(node->right); que.emplace(node->right);
} }
} }

@ -41,8 +41,7 @@ namespace hello_algo.chapter_tree
{ {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
TreeNode? root = TreeNode.ArrToTree(new int?[] { TreeNode? root = TreeNode.ArrToTree(new int?[] { 1, 2, 3, 4, 5, 6, 7 });
1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null});
Console.WriteLine("\n初始化二叉树\n"); Console.WriteLine("\n初始化二叉树\n");
PrintUtil.PrintTree(root); PrintUtil.PrintTree(root);

@ -57,8 +57,7 @@ namespace hello_algo.chapter_tree
{ {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
TreeNode? root = TreeNode.ArrToTree(new int?[] { TreeNode? root = TreeNode.ArrToTree(new int?[] { 1, 2, 3, 4, 5, 6, 7 });
1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null});
Console.WriteLine("\n初始化二叉树\n"); Console.WriteLine("\n初始化二叉树\n");
PrintUtil.PrintTree(root); PrintUtil.PrintTree(root);

@ -19,7 +19,7 @@ namespace hello_algo.include
} }
/** /**
* Generate a binary tree with an array * Generate a binary tree given an array
* @param arr * @param arr
* @return * @return
*/ */
@ -31,22 +31,22 @@ namespace hello_algo.include
TreeNode root = new TreeNode((int) arr[0]); TreeNode root = new TreeNode((int) arr[0]);
Queue<TreeNode> queue = new Queue<TreeNode>(); Queue<TreeNode> queue = new Queue<TreeNode>();
queue.Enqueue(root); queue.Enqueue(root);
int i = 1; int i = 0;
while (queue.Count != 0) while (queue.Count != 0)
{ {
TreeNode node = queue.Dequeue(); TreeNode node = queue.Dequeue();
if (++i >= arr.Length) break;
if (arr[i] != null) if (arr[i] != null)
{ {
node.left = new TreeNode((int) arr[i]); node.left = new TreeNode((int) arr[i]);
queue.Enqueue(node.left); queue.Enqueue(node.left);
} }
i++; if (++i >= arr.Length) break;
if (arr[i] != null) if (arr[i] != null)
{ {
node.right = new TreeNode((int) arr[i]); node.right = new TreeNode((int) arr[i]);
queue.Enqueue(node.right); queue.Enqueue(node.right);
} }
i++;
} }
return root; return root;
} }

@ -14,11 +14,11 @@ import (
func TestLevelOrder(t *testing.T) { func TestLevelOrder(t *testing.T) {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
root := ArrayToTree([]int{1, 2, 3, 4, 5, 6, 7}) root := ArrToTree([]int{1, 2, 3, 4, 5, 6, 7})
fmt.Println("初始化二叉树: ") fmt.Println("\n初始化二叉树: ")
PrintTree(root) PrintTree(root)
// 层序遍历 // 层序遍历
nums := levelOrder(root) nums := levelOrder(root)
fmt.Println("层序遍历的结点打印序列 =", nums) fmt.Println("\n层序遍历的结点打印序列 =", nums)
} }

@ -14,22 +14,22 @@ import (
func TestPreInPostOrderTraversal(t *testing.T) { func TestPreInPostOrderTraversal(t *testing.T) {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
root := ArrayToTree([]int{1, 2, 3, 4, 5, 6, 7}) root := ArrToTree([]int{1, 2, 3, 4, 5, 6, 7})
fmt.Println("初始化二叉树: ") fmt.Println("\n初始化二叉树: ")
PrintTree(root) PrintTree(root)
// 前序遍历 // 前序遍历
nums = nil nums = nil
preOrder(root) preOrder(root)
fmt.Println("前序遍历的结点打印序列 =", nums) fmt.Println("\n前序遍历的结点打印序列 =", nums)
// 中序遍历 // 中序遍历
nums = nil nums = nil
inOrder(root) inOrder(root)
fmt.Println("中序遍历的结点打印序列 =", nums) fmt.Println("\n中序遍历的结点打印序列 =", nums)
// 后序遍历 // 后序遍历
nums = nil nums = nil
postOrder(root) postOrder(root)
fmt.Println("后序遍历的结点打印序列 =", nums) fmt.Println("\n后序遍历的结点打印序列 =", nums)
} }

@ -22,8 +22,8 @@ func NewTreeNode(v int) *TreeNode {
} }
} }
// ArrayToTree Generate a binary tree with an array // ArrToTree Generate a binary tree given an array
func ArrayToTree(arr []int) *TreeNode { func ArrToTree(arr []int) *TreeNode {
if len(arr) <= 0 { if len(arr) <= 0 {
return nil return nil
} }
@ -31,19 +31,19 @@ func ArrayToTree(arr []int) *TreeNode {
// Let container.list as queue // Let container.list as queue
queue := list.New() queue := list.New()
queue.PushBack(root) queue.PushBack(root)
i := 1 i := 0
for queue.Len() > 0 { for queue.Len() > 0 {
// poll // poll
node := queue.Remove(queue.Front()).(*TreeNode) node := queue.Remove(queue.Front()).(*TreeNode)
i++
if i < len(arr) { if i < len(arr) {
node.Left = NewTreeNode(arr[i]) node.Left = NewTreeNode(arr[i])
queue.PushBack(node.Left) queue.PushBack(node.Left)
i++
} }
i++
if i < len(arr) { if i < len(arr) {
node.Right = NewTreeNode(arr[i]) node.Right = NewTreeNode(arr[i])
queue.PushBack(node.Right) queue.PushBack(node.Right)
i++
} }
} }
return root return root

@ -11,7 +11,7 @@ import (
func TestTreeNode(t *testing.T) { func TestTreeNode(t *testing.T) {
arr := []int{2, 3, 5, 6, 7} arr := []int{2, 3, 5, 6, 7}
node := ArrayToTree(arr) node := ArrToTree(arr)
// print tree // print tree
PrintTree(node) PrintTree(node)

@ -0,0 +1,115 @@
/**
* File: my_heap.java
* Created Time: 2023-01-07
* Author: Krahets (krahets@163.com)
*/
package chapter_heap;
import include.*;
import java.util.*;
class MaxHeap {
private List<Integer> heap;
public MaxHeap() {
heap = new ArrayList<>();
}
public MaxHeap(List<Integer> nums) {
// 将元素拷贝至堆中
heap = new ArrayList<>(nums);
// 堆化除叶结点外的其他所有结点
for (int i = parent(size() - 1); i >= 0; i--) {
heapify(i);
}
}
/* 获取左子结点 */
private int left(int i) {
return 2 * i + 1;
}
/* 获取右子结点 */
private int right(int i) {
return 2 * i + 2;
}
/* 获取父结点 */
private int parent(int i) {
return (i - 1) / 2;
}
/* 交换元素 */
private void swap(int i, int j) {
int tmp = heap.get(i);
heap.set(i, j);
heap.set(j, tmp);
}
public int size() {
return heap.size();
}
public boolean isEmpty() {
return size() == 0;
}
/* 获取堆顶元素 */
public int peek() {
return heap.get(0);
}
/* 元素入堆 */
public void push(int val) {
heap.add(val);
// 从底至顶堆化
int i = size();
while (true) {
int p = parent(i);
if (p < 0 || heap.get(i) > heap.get(p))
break;
swap(i, p);
i = p;
}
}
/* 元素出堆 */
public int poll() {
// 判空处理
if (isEmpty())
throw new EmptyStackException();
// 交换根结点与右下角(即最后一个)结点
swap(0, size() - 1);
// 删除结点
int val = heap.remove(size() - 1);
// 从顶至底堆化
heapify(0);
// 返回堆顶元素
return val;
}
/* 从结点 i 开始,从顶至底堆化 */
private void heapify(int i) {
while (true) {
// 判断结点 i, l, r 中的最大结点,记为 ma
int l = left(i), r = right(i), ma = i;
if (heap.get(l) > heap.get(ma)) ma = l;
if (heap.get(r) > heap.get(ma)) ma = r;
// 若结点 i 最大,则无需继续堆化,跳出
if (ma == i) break;
// 交换结点 i 与结点 max
swap(i, ma);
// 循环向下堆化
i = ma;
}
}
}
public class my_heap {
public static void main(String[] args) {
}
}

@ -30,8 +30,7 @@ public class binary_tree_bfs {
public static void main(String[] args) { public static void main(String[] args) {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
TreeNode root = TreeNode.arrToTree(new Integer[] { TreeNode root = TreeNode.arrToTree(new Integer[] { 1, 2, 3, 4, 5, 6, 7 });
1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null });
System.out.println("\n初始化二叉树\n"); System.out.println("\n初始化二叉树\n");
PrintUtil.printTree(root); PrintUtil.printTree(root);

@ -43,8 +43,7 @@ public class binary_tree_dfs {
public static void main(String[] args) { public static void main(String[] args) {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
TreeNode root = TreeNode.arrToTree(new Integer[] { TreeNode root = TreeNode.arrToTree(new Integer[] { 1, null, 3, 4, 5 });
1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null});
System.out.println("\n初始化二叉树\n"); System.out.println("\n初始化二叉树\n");
PrintUtil.printTree(root); PrintUtil.printTree(root);

@ -8,6 +8,7 @@ package include;
import java.util.*; import java.util.*;
class Trunk { class Trunk {
Trunk prev; Trunk prev;
String str; String str;
@ -103,4 +104,11 @@ public class PrintUtil {
System.out.println(kv.getKey() + " -> " + kv.getValue()); System.out.println(kv.getKey() + " -> " + kv.getValue());
} }
} }
public static void printHeap(PriorityQueue<Integer> queue) {
Integer[] nums = (Integer[])queue.toArray();
TreeNode root = TreeNode.arrToTree(nums);
printTree(root);
}
} }

@ -22,7 +22,7 @@ public class TreeNode {
} }
/** /**
* Generate a binary tree with an array * Generate a binary tree given an array
* @param arr * @param arr
* @return * @return
*/ */
@ -32,19 +32,19 @@ public class TreeNode {
TreeNode root = new TreeNode(arr[0]); TreeNode root = new TreeNode(arr[0]);
Queue<TreeNode> queue = new LinkedList<>() {{ add(root); }}; Queue<TreeNode> queue = new LinkedList<>() {{ add(root); }};
int i = 1; int i = 0;
while(!queue.isEmpty()) { while(!queue.isEmpty()) {
TreeNode node = queue.poll(); TreeNode node = queue.poll();
if (++i >= arr.length) break;
if(arr[i] != null) { if(arr[i] != null) {
node.left = new TreeNode(arr[i]); node.left = new TreeNode(arr[i]);
queue.add(node.left); queue.add(node.left);
} }
i++; if (++i >= arr.length) break;
if(arr[i] != null) { if(arr[i] != null) {
node.right = new TreeNode(arr[i]); node.right = new TreeNode(arr[i]);
queue.add(node.right); queue.add(node.right);
} }
i++;
} }
return root; return root;
} }
@ -71,20 +71,4 @@ public class TreeNode {
} }
return list; return list;
} }
/**
* Get a tree node with specific value in a binary tree
* @param root
* @param val
* @return
*/
public static TreeNode getTreeNode(TreeNode root, int val) {
if (root == null)
return null;
if (root.val == val)
return root;
TreeNode left = getTreeNode(root.left, val);
TreeNode right = getTreeNode(root.right, val);
return left != null ? left : right;
}
} }

@ -28,7 +28,7 @@ function hierOrder(root) {
/* Driver Code */ /* Driver Code */
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
var root = arrToTree([1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null]); var root = arrToTree([1, 2, 3, 4, 5, 6, 7]);
console.log("\n初始化二叉树\n"); console.log("\n初始化二叉树\n");
printTree(root); printTree(root);

@ -40,7 +40,7 @@ function postOrder(root) {
/* Driver Code */ /* Driver Code */
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
var root = arrToTree([1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null]); var root = arrToTree([1, 2, 3, 4, 5, 6, 7]);
console.log("\n初始化二叉树\n"); console.log("\n初始化二叉树\n");
printTree(root); printTree(root);
@ -58,4 +58,3 @@ console.log("\n中序遍历的结点打印序列 = " + list);
list.length = 0; list.length = 0;
postOrder(root); postOrder(root);
console.log("\n后序遍历的结点打印序列 = " + list); console.log("\n后序遍历的结点打印序列 = " + list);

@ -14,7 +14,7 @@ function TreeNode(val, left, right) {
} }
/** /**
* Generate a binary tree with an array * Generate a binary tree given an array
* @param arr * @param arr
* @return * @return
*/ */
@ -24,20 +24,21 @@ function arrToTree(arr) {
let root = new TreeNode(arr[0]); let root = new TreeNode(arr[0]);
let queue = [root] let queue = [root]
let i = 1; let i = 0;
while (queue.length) { while (queue.length) {
let node = queue.shift(); let node = queue.shift();
if (++i >= arr.length) break;
if (arr[i] !== null) { if (arr[i] !== null) {
node.left = new TreeNode(arr[i]); node.left = new TreeNode(arr[i]);
queue.push(node.left); queue.push(node.left);
} }
i++; if (++i >= arr.length) break;
if (arr[i] !== null) { if (arr[i] !== null) {
node.right = new TreeNode(arr[i]); node.right = new TreeNode(arr[i]);
queue.push(node.right); queue.push(node.right);
} }
i++;
} }
return root; return root;
} }

@ -138,7 +138,7 @@ class BinarySearchTree:
""" Driver Code """ """ Driver Code """
if __name__ == "__main__": if __name__ == "__main__":
# 初始化二叉搜索树 # 初始化二叉搜索树
nums = list(range(1, 16)) nums = list(range(1, 16)) # [1, 2, ..., 15]
bst = BinarySearchTree(nums=nums) bst = BinarySearchTree(nums=nums)
print("\n初始化的二叉树为\n") print("\n初始化的二叉树为\n")
print_tree(bst.root) print_tree(bst.root)

@ -36,5 +36,5 @@ if __name__ == "__main__":
print_tree(n1) print_tree(n1)
# 删除结点 # 删除结点
n1.left = n2 n1.left = n2
print("\n删除结点 P 后\n"); print("\n删除结点 P 后\n")
print_tree(n1) print_tree(n1)

@ -32,7 +32,7 @@ def hier_order(root: TreeNode):
if __name__ == "__main__": if __name__ == "__main__":
# 初始化二叉树 # 初始化二叉树
# 这里借助了一个从数组直接生成二叉树的函数 # 这里借助了一个从数组直接生成二叉树的函数
root = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7, None, None, None, None, None, None, None, None]) root = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7])
print("\n初始化二叉树\n") print("\n初始化二叉树\n")
print_tree(root) print_tree(root)

@ -45,7 +45,7 @@ def post_order(root: typing.Optional[TreeNode]):
if __name__ == "__main__": if __name__ == "__main__":
# 初始化二叉树 # 初始化二叉树
# 这里借助了一个从数组直接生成二叉树的函数 # 这里借助了一个从数组直接生成二叉树的函数
root = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7, None, None, None, None, None, None, None, None]) root = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7])
print("\n初始化二叉树\n") print("\n初始化二叉树\n")
print_tree(root) print_tree(root)

@ -26,39 +26,30 @@ class TreeNode:
def list_to_tree(arr): def list_to_tree(arr):
"""Generate a binary tree with a list """Generate a binary tree with a list
Args:
arr ([type]): [description]
Returns:
[type]: [description]
""" """
if not arr: if not arr:
return None return None
i = 1
root = TreeNode(int(arr[0])) i = 0
queue = collections.deque() root = TreeNode(arr[0])
queue.append(root) queue = collections.deque([root])
while queue: while queue:
node = queue.popleft() node = queue.popleft()
i += 1
if i >= len(arr): break
if arr[i] != None: if arr[i] != None:
node.left = TreeNode(int(arr[i])) node.left = TreeNode(arr[i])
queue.append(node.left) queue.append(node.left)
i += 1 i += 1
if i >= len(arr): break
if arr[i] != None: if arr[i] != None:
node.right = TreeNode(int(arr[i])) node.right = TreeNode(arr[i])
queue.append(node.right) queue.append(node.right)
i += 1
return root return root
def tree_to_list(root): def tree_to_list(root):
"""Serialize a tree into an array """Serialize a tree into an array
Args:
root ([type]): [description]
Returns:
[type]: [description]
""" """
if not root: return [] if not root: return []
queue = collections.deque() queue = collections.deque()
@ -75,13 +66,6 @@ def tree_to_list(root):
def get_tree_node(root, val): def get_tree_node(root, val):
"""Get a tree node with specific value in a binary tree """Get a tree node with specific value in a binary tree
Args:
root ([type]): [description]
val ([type]): [description]
Returns:
[type]: [description]
""" """
if not root: if not root:
return return

@ -30,7 +30,7 @@ function hierOrder(root: TreeNode | null): number[] {
/* Driver Code */ /* Driver Code */
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
var root = arrToTree([1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null]); var root = arrToTree([1, 2, 3, 4, 5, 6, 7]);
console.log('\n初始化二叉树\n'); console.log('\n初始化二叉树\n');
printTree(root); printTree(root);

@ -47,7 +47,7 @@ function postOrder(root: TreeNode | null): void {
/* Driver Code */ /* Driver Code */
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
const root = arrToTree([1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null]); const root = arrToTree([1, 2, 3, 4, 5, 6, 7]);
console.log('\n初始化二叉树\n'); console.log('\n初始化二叉树\n');
printTree(root); printTree(root);

@ -20,7 +20,7 @@ class TreeNode {
} }
/** /**
* Generate a binary tree with an array * Generate a binary tree given an array
* @param arr * @param arr
* @return * @return
*/ */
@ -31,19 +31,19 @@ function arrToTree(arr: (number | null)[]): TreeNode | null {
const root = new TreeNode(arr[0] as number); const root = new TreeNode(arr[0] as number);
const queue = [root]; const queue = [root];
let i = 1; let i = 0;
while (queue.length) { while (queue.length) {
let node = queue.shift() as TreeNode; let node = queue.shift() as TreeNode;
if (++i >= arr.length) break;
if (arr[i] !== null) { if (arr[i] !== null) {
node.left = new TreeNode(arr[i] as number); node.left = new TreeNode(arr[i] as number);
queue.push(node.left); queue.push(node.left);
} }
i++; if (++i >= arr.length) break;
if (arr[i] !== null) { if (arr[i] !== null) {
node.right = new TreeNode(arr[i] as number); node.right = new TreeNode(arr[i] as number);
queue.push(node.right); queue.push(node.right);
} }
i++;
} }
return root; return root;
} }

@ -2,26 +2,48 @@
「堆 Heap」是一种特殊的树状数据结构并且是一颗「完全二叉树」。堆主要分为两种 「堆 Heap」是一种特殊的树状数据结构并且是一颗「完全二叉树」。堆主要分为两种
- 「大顶堆 Max Heap」任意父结点的值 > 其子结点的值,因此根结点的值最大; - 「大顶堆 Max Heap」任意结点的值 $\geq$ 其子结点的值,因此根结点的值最大;
- 「小顶堆 Min Heap」任意父结点的值 < 其子结点的值,因此根结点的值最小; - 「小顶堆 Min Heap」任意结点的值 $\leq$ 其子结点的值,因此根结点的值最小;
(图) (图)
!!! tip "" !!! tip ""
大顶堆和小顶堆的定义、性质、操作本质上是一样的。区别只是大顶堆在求最大值,小顶堆在求最小值。在下文中,我们将统一用「大顶堆」来举例,「小顶堆」的用法与实现可以简单地将所有 $>$ ($<$) 替换为 $<$ ($>$) 即可。 大顶堆和小顶堆的定义、性质、操作本质上是相同的,区别只是大顶堆在求最大值,小顶堆在求最小值。
## 堆常用操作 ## 堆常用操作
堆的初始化 值得说明的是,多数编程语言提供的是「优先队列 Priority Queue」其是一种抽象数据结构**定义为具有出队优先级的队列**
获取堆顶元素 而恰好,堆的定义与优先队列的操作逻辑完全吻合,大顶堆就是一个元素从大到小出队的优先队列。从使用角度看,我们可以将「优先队列」和「堆」理解为等价的数据结构,下文将统一使用 “堆” 这个名称
添加与删除元素。 堆的常用操作见下表(方法命名以 Java 为例)。
<p align="center"> Table. 堆的常用操作 </p>
<div class="center-table" markdown>
| 方法 | 描述 |
| --------- | -------------------------------------------- |
| add() | 元素入堆 |
| poll() | 堆顶元素出堆 |
| peek() | 访问堆顶元素(大 / 小顶堆分别为最大 / 小值) |
| size() | 获取堆的元素数量 |
| isEmpty() | 判断堆是否为空 |
</div>
```java
```
## 堆的实现 ## 堆的实现
在二叉树章节中,我们讲过二叉树的数组表示方法,并且提到完全二叉树非常适合用数组来表示,因此我们一般使用「数组」来存储「堆」。 !!! tip
下文使用「大顶堆」来举例,「小顶堆」的用法与实现可以简单地将所有 $>$ ($<$) 替换为 $<$ ($>$) 即可。
我们一般使用「数组」来存储「堆」,这是因为完全二叉树非常适合用数组来表示(在二叉树章节有详细解释)。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Loading…
Cancel
Save