Rust 常见内置 Traits 详解(一):https://ipotato.me/article/59

    BinaryHrap 源码解析:https://zhuanlan.zhihu.com/p/305107063

    1. #[stable(feature = "rust1", since = "1.0.0")]
    2. #[cfg_attr(not(test), rustc_diagnostic_item = "BinaryHeap")]
    3. pub struct BinaryHeap<T> {
    4. data: Vec<T>, // T -> Ord
    5. }
    6. impl<T: Ord> BinaryHeap<T> {
    7. /// Creates an empty `BinaryHeap` as a max-heap.
    8. ///
    9. /// # Examples
    10. ///
    11. /// Basic usage:
    12. ///
    13. ///
    1. /// use std::collections::BinaryHeap;
    2. /// let mut heap = BinaryHeap::new();
    3. /// heap.push(4);
    4. /// ```
    5. #[stable(feature = "rust1", since = "1.0.0")]
    6. #[must_use]
    7. pub fn new() -> BinaryHeap<T> {
    8. BinaryHeap { data: vec![] }
    9. }
    10. /// Returns the length of the binary heap.
    11. ///
    12. /// # Examples
    13. ///
    14. /// Basic usage:
    15. ///
    16. /// ```
    17. /// use std::collections::BinaryHeap;
    18. /// let heap = BinaryHeap::from([1, 3]);
    19. ///
    20. /// assert_eq!(heap.len(), 2);
    21. /// ```
    22. #[must_use]
    23. #[stable(feature = "rust1", since = "1.0.0")]
    24. pub fn len(&self) -> usize {
    25. self.data.len()
    26. }
    27. /// Pushes an item onto the binary heap.
    28. ///
    29. /// # Examples
    30. ///
    31. /// Basic usage:
    32. ///
    33. /// ```
    34. /// use std::collections::BinaryHeap;
    35. /// let mut heap = BinaryHeap::new();
    36. /// heap.push(3);
    37. /// heap.push(5);
    38. /// heap.push(1);
    39. ///
    40. /// assert_eq!(heap.len(), 3);
    41. /// assert_eq!(heap.peek(), Some(&5));
    42. /// ```
    43. ///
    44. /// # Time complexity
    45. ///
    46. /// The expected cost of `push`, averaged over every possible ordering of
    47. /// the elements being pushed, and over a sufficiently large number of
    48. /// pushes, is *O*(1). This is the most meaningful cost metric when pushing
    49. /// elements that are *not* already in any sorted pattern.
    50. ///
    51. /// The time complexity degrades if elements are pushed in predominantly
    52. /// ascending order. In the worst case, elements are pushed in ascending
    53. /// sorted order and the amortized cost per push is *O*(log(*n*)) against a heap
    54. /// containing *n* elements.
    55. ///
    56. /// The worst case cost of a *single* call to `push` is *O*(*n*). The worst case
    57. /// occurs when capacity is exhausted and needs a resize. The resize cost
    58. /// has been amortized in the previous figures.
    59. #[stable(feature = "rust1", since = "1.0.0")]
    60. pub fn push(&mut self, item: T) {
    61. let old_len = self.len();
    62. self.data.push(item);
    63. // SAFETY: Since we pushed a new item it means that
    64. // old_len = self.len() - 1 < self.len()
    65. unsafe { self.sift_up(0, old_len) };
    66. }
    67. // The implementations of sift_up and sift_down use unsafe blocks in
    68. // order to move an element out of the vector (leaving behind a
    69. // hole), shift along the others and move the removed element back into the
    70. // vector at the final location of the hole.
    71. // The `Hole` type is used to represent this, and make sure
    72. // the hole is filled back at the end of its scope, even on panic.
    73. // Using a hole reduces the constant factor compared to using swaps,
    74. // which involves twice as many moves.
    75. /// # Safety
    76. ///
    77. /// The caller must guarantee that `pos < self.len()`.
    78. unsafe fn sift_up(&mut self, start: usize, pos: usize) -> usize {
    79. // Take out the value at `pos` and create a hole.
    80. // SAFETY: The caller guarantees that pos < self.len()
    81. let mut hole = unsafe { Hole::new(&mut self.data, pos) };
    82. while hole.pos() > start {
    83. let parent = (hole.pos() - 1) / 2;
    84. // SAFETY: hole.pos() > start >= 0, which means hole.pos() > 0
    85. // and so hole.pos() - 1 can't underflow.
    86. // This guarantees that parent < hole.pos() so
    87. // it's a valid index and also != hole.pos().
    88. // valid 正当的;有效的,有根据的
    89. // underflow 下溢
    90. // guarantee 保证
    91. if hole.element() <= unsafe { hole.get(parent) } {
    92. break;
    93. }
    94. // SAFETY: Same as above
    95. unsafe { hole.move_to(parent) };
    96. }
    97. hole.pos()
    98. }

    }

    1. javascript 最小堆 leetcode 丑数)链接:[https://leetcode.cn/problems/ugly-number-ii/solution/chou-shu-ii-by-leetcode-solution-uoqd/](https://leetcode.cn/problems/ugly-number-ii/solution/chou-shu-ii-by-leetcode-solution-uoqd/)
    2. ```javascript
    3. var nthUglyNumber = function(n) {
    4. const factors = [2, 3, 5];
    5. const seen = new Set();
    6. const heap = new MinHeap();
    7. seen.add(1);
    8. heap.insert(1);
    9. let ugly = 0;
    10. for (let i = 0; i < n; i++) {
    11. ugly = heap.pop();
    12. for (const factor of factors) {
    13. const next = ugly * factor;
    14. if (!seen.has(next)) {
    15. seen.add(next);
    16. heap.insert(next);
    17. }
    18. }
    19. }
    20. return ugly;
    21. };
    22. // 最小堆
    23. class MinHeap {
    24. constructor() {
    25. this.heap = [];
    26. }
    27. getParentIndex(i) {
    28. return (i - 1) >> 1;
    29. }
    30. getLeftIndex(i) {
    31. return i * 2 + 1;
    32. }
    33. getRightIndex(i) {
    34. return i * 2 + 2;
    35. }
    36. shiftUp(index) {
    37. if(index === 0) { return; }
    38. const parentIndex = this.getParentIndex(index);
    39. if(this.heap[parentIndex] > this.heap[index]){
    40. this.swap(parentIndex, index);
    41. this.shiftUp(parentIndex);
    42. }
    43. }
    44. swap(i1, i2) {
    45. const temp = this.heap[i1];
    46. this.heap[i1]= this.heap[i2];
    47. this.heap[i2] = temp;
    48. }
    49. insert(value) {
    50. this.heap.push(value);
    51. this.shiftUp(this.heap.length - 1);
    52. }
    53. pop() {
    54. this.heap[0] = this.heap.pop();
    55. this.shiftDown(0);
    56. return this.heap[0];
    57. }
    58. shiftDown(index) {
    59. const leftIndex = this.getLeftIndex(index);
    60. const rightIndex = this.getRightIndex(index);
    61. if (this.heap[leftIndex] < this.heap[index]) {
    62. this.swap(leftIndex, index);
    63. this.shiftDown(leftIndex);
    64. }
    65. if (this.heap[rightIndex] < this.heap[index]){
    66. this.swap(rightIndex, index);
    67. this.shiftDown(rightIndex);
    68. }
    69. }
    70. peek() {
    71. return this.heap[0];
    72. }
    73. size() {
    74. return this.heap.length;
    75. }
    76. }