authorgravatar for saurabh.m@proton.meSaurabh Mishra <saurabh.m@proton.me> 2026-02-18 13:24:03-08:00
committergravatar for saurabh.m@proton.meSaurabh Mishra <saurabh.m@proton.me> 2026-02-18 13:24:03-08:00
log5140455264347f8bf869edae71faa8848e92dabd
tree73d652fc11b1db24154ac5246f03beb22bb95dd8
parent293710c1cd3160787e882113014c022ce665d16d

min heap is formed with less than comparison


1 files changed, 59 insertions(+), 56 deletions(-)

lib/std/priority_dequeue.zig+59-56
......@@ -449,17 +449,20 @@ pub fn PriorityDequeue(comptime T: type, comptime Context: type, comptime compar
449449 };
450450}
451451
452/// If a min heap is constructed from slice `{5, 8, 2, 9, 7, 1, 4, 4}` using this
453/// method, then the elements will be in order: {1, 2, 4, 4, 5, 7, 8, 9}
452454fn lessThanComparison(context: void, a: u32, b: u32) Order {
453455 _ = context;
454456 return std.math.order(a, b);
455457}
456458
457const PDQ = PriorityDequeue(u32, void, lessThanComparison);
459/// Elements with lower priority will be removed first
460const MinHeap = PriorityDequeue(u32, void, lessThanComparison);
458461
459test "push and pop min" {
462test "push and pop min in min heap" {
460463 const gpa = std.testing.allocator;
461464
462 var queue: PDQ = .empty;
465 var queue: MinHeap = .empty;
463466 defer queue.deinit(gpa);
464467
465468 try queue.push(gpa, 54);
......@@ -506,10 +509,10 @@ test "push and pop min structs" {
506509 try expectEqual(@as(u32, 54), queue.popMin().?.size);
507510}
508511
509test "push and pop max" {
512test "push and pop max in min heap" {
510513 const gpa = std.testing.allocator;
511514
512 var queue: PDQ = .empty;
515 var queue: MinHeap = .empty;
513516 defer queue.deinit(gpa);
514517
515518 try queue.push(gpa, 54);
......@@ -527,10 +530,10 @@ test "push and pop max" {
527530 try expectEqual(@as(u32, 7), queue.popMax());
528531}
529532
530test "push and pop same min" {
533test "push and pop same min in min heap" {
531534 const gpa = std.testing.allocator;
532535
533 var queue: PDQ = .empty;
536 var queue: MinHeap = .empty;
534537 defer queue.deinit(gpa);
535538
536539 try queue.push(gpa, 1);
......@@ -548,10 +551,10 @@ test "push and pop same min" {
548551 try expectEqual(@as(u32, 2), queue.popMin());
549552}
550553
551test "push and pop same max" {
554test "push and pop same max in min heap" {
552555 const gpa = std.testing.allocator;
553556
554 var queue: PDQ = .empty;
557 var queue: MinHeap = .empty;
555558 defer queue.deinit(gpa);
556559
557560 try queue.push(gpa, 1);
......@@ -569,20 +572,20 @@ test "push and pop same max" {
569572 try expectEqual(@as(u32, 1), queue.popMax());
570573}
571574
572test "popOrNull empty" {
575test "pop empty in min heap" {
573576 const gpa = std.testing.allocator;
574577
575 var queue: PDQ = .empty;
578 var queue: MinHeap = .empty;
576579 defer queue.deinit(gpa);
577580
578581 try expect(queue.popMin() == null);
579582 try expect(queue.popMax() == null);
580583}
581584
582test "edge case 3 elements" {
585test "edge case 3 elements popMin in min heap" {
583586 const gpa = std.testing.allocator;
584587
585 var queue: PDQ = .empty;
588 var queue: MinHeap = .empty;
586589 defer queue.deinit(gpa);
587590
588591 try queue.push(gpa, 9);
......@@ -594,10 +597,10 @@ test "edge case 3 elements" {
594597 try expectEqual(@as(u32, 9), queue.popMin());
595598}
596599
597test "edge case 3 elements max" {
600test "edge case 3 elements popmax in min heap" {
598601 const gpa = std.testing.allocator;
599602
600 var queue: PDQ = .empty;
603 var queue: MinHeap = .empty;
601604 defer queue.deinit(gpa);
602605
603606 try queue.push(gpa, 9);
......@@ -609,10 +612,10 @@ test "edge case 3 elements max" {
609612 try expectEqual(@as(u32, 2), queue.popMax());
610613}
611614
612test "peekMin" {
615test "peekMin in min heap" {
613616 const gpa = std.testing.allocator;
614617
615 var queue: PDQ = .empty;
618 var queue: MinHeap = .empty;
616619 defer queue.deinit(gpa);
617620
618621 try expect(queue.peekMin() == null);
......@@ -625,10 +628,10 @@ test "peekMin" {
625628 try expect(queue.peekMin().? == 2);
626629}
627630
628test "peekMax" {
631test "peekMax in min heap" {
629632 const gpa = std.testing.allocator;
630633
631 var queue: PDQ = .empty;
634 var queue: MinHeap = .empty;
632635 defer queue.deinit(gpa);
633636
634637 try expect(queue.peekMin() == null);
......@@ -641,10 +644,10 @@ test "peekMax" {
641644 try expect(queue.peekMax().? == 9);
642645}
643646
644test "sift up with odd indices, popMin" {
647test "sift up with odd indices and popMin in min heap" {
645648 const gpa = std.testing.allocator;
646649
647 var queue: PDQ = .empty;
650 var queue: MinHeap = .empty;
648651 defer queue.deinit(gpa);
649652
650653 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
......@@ -658,10 +661,10 @@ test "sift up with odd indices, popMin" {
658661 }
659662}
660663
661test "sift up with odd indices, popMax" {
664test "sift up with odd indices and popMax in min heap" {
662665 const gpa = std.testing.allocator;
663666
664 var queue: PDQ = .empty;
667 var queue: MinHeap = .empty;
665668 defer queue.deinit(gpa);
666669
667670 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
......@@ -675,10 +678,10 @@ test "sift up with odd indices, popMax" {
675678 }
676679}
677680
678test "pushSlice min" {
681test "pushSlice in min heap and popMin" {
679682 const gpa = std.testing.allocator;
680683
681 var queue: PDQ = .empty;
684 var queue: MinHeap = .empty;
682685 defer queue.deinit(gpa);
683686
684687 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
......@@ -690,10 +693,10 @@ test "pushSlice min" {
690693 }
691694}
692695
693test "pushSlice max" {
696test "pushSlice in min heap and popMax" {
694697 const gpa = std.testing.allocator;
695698
696 var queue: PDQ = .empty;
699 var queue: MinHeap = .empty;
697700 defer queue.deinit(gpa);
698701
699702 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
......@@ -705,26 +708,26 @@ test "pushSlice max" {
705708 }
706709}
707710
708test "fromOwnedSlice trivial case 0" {
711test "fromOwnedSlice trivial case 0 min heap" {
709712 const gpa = std.testing.allocator;
710713
711714 const items = [0]u32{};
712715 const queue_items = try gpa.dupe(u32, &items);
713716
714 var queue = PDQ.fromOwnedSlice(queue_items[0..], {});
717 var queue: MinHeap = .fromOwnedSlice(queue_items[0..], {});
715718 defer queue.deinit(gpa);
716719
717720 try expectEqual(@as(usize, 0), queue.len);
718721 try expect(queue.popMin() == null);
719722}
720723
721test "fromOwnedSlice trivial case 1" {
724test "fromOwnedSlice trivial case 1 min heap" {
722725 const gpa = std.testing.allocator;
723726
724727 const items = [1]u32{1};
725728 const queue_items = try gpa.dupe(u32, &items);
726729
727 var queue = PDQ.fromOwnedSlice(queue_items[0..], {});
730 var queue: MinHeap = .fromOwnedSlice(queue_items[0..], {});
728731 defer queue.deinit(gpa);
729732
730733 try expectEqual(@as(usize, 1), queue.len);
......@@ -732,13 +735,13 @@ test "fromOwnedSlice trivial case 1" {
732735 try expect(queue.popMin() == null);
733736}
734737
735test "fromOwnedSlice" {
738test "fromOwnedSlice min heap" {
736739 const gpa = std.testing.allocator;
737740
738741 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
739742 const queue_items = try gpa.dupe(u32, items[0..]);
740743
741 var queue = PDQ.fromOwnedSlice(queue_items[0..], {});
744 var queue: MinHeap = .fromOwnedSlice(queue_items[0..], {});
742745 defer queue.deinit(gpa);
743746
744747 const sorted_items = [_]u32{ 1, 2, 5, 6, 7, 7, 11, 12, 13, 14, 15, 15, 16, 21, 22, 24, 24, 25 };
......@@ -747,10 +750,10 @@ test "fromOwnedSlice" {
747750 }
748751}
749752
750test "update min queue" {
753test "update and popMin in min heap" {
751754 const gpa = std.testing.allocator;
752755
753 var queue: PDQ = .empty;
756 var queue: MinHeap = .empty;
754757 defer queue.deinit(gpa);
755758
756759 try queue.push(gpa, 55);
......@@ -764,10 +767,10 @@ test "update min queue" {
764767 try expectEqual(@as(u32, 5), queue.popMin());
765768}
766769
767test "update same min queue" {
770test "update same element and popMin in min heap" {
768771 const gpa = std.testing.allocator;
769772
770 var queue: PDQ = .empty;
773 var queue: MinHeap = .empty;
771774 defer queue.deinit(gpa);
772775
773776 try queue.push(gpa, 1);
......@@ -782,10 +785,10 @@ test "update same min queue" {
782785 try expectEqual(@as(u32, 5), queue.popMin());
783786}
784787
785test "update max queue" {
788test "update and popMax in min heap" {
786789 const gpa = std.testing.allocator;
787790
788 var queue: PDQ = .empty;
791 var queue: MinHeap = .empty;
789792 defer queue.deinit(gpa);
790793
791794 try queue.push(gpa, 55);
......@@ -800,10 +803,10 @@ test "update max queue" {
800803 try expectEqual(@as(u32, 1), queue.popMax());
801804}
802805
803test "update same max queue" {
806test "update same element and popMax in min heap" {
804807 const gpa = std.testing.allocator;
805808
806 var queue: PDQ = .empty;
809 var queue: MinHeap = .empty;
807810 defer queue.deinit(gpa);
808811
809812 try queue.push(gpa, 1);
......@@ -818,10 +821,10 @@ test "update same max queue" {
818821 try expectEqual(@as(u32, 1), queue.popMax());
819822}
820823
821test "update after pop" {
824test "update after pop in min heap" {
822825 const gpa = std.testing.allocator;
823826
824 var queue: PDQ = .empty;
827 var queue: MinHeap = .empty;
825828 defer queue.deinit(gpa);
826829
827830 try queue.push(gpa, 1);
......@@ -829,10 +832,10 @@ test "update after pop" {
829832 try expectError(error.ElementNotFound, queue.update(1, 1));
830833}
831834
832test "iterator" {
835test "min heap iterator" {
833836 const gpa = std.testing.allocator;
834837
835 var queue: PDQ = .empty;
838 var queue: MinHeap = .empty;
836839 var map = std.AutoHashMap(u32, void).init(testing.allocator);
837840 defer {
838841 queue.deinit(gpa);
......@@ -853,10 +856,10 @@ test "iterator" {
853856 try expectEqual(@as(usize, 0), map.count());
854857}
855858
856test "pop at index" {
859test "pop at index in min heap" {
857860 const gpa = std.testing.allocator;
858861
859 var queue: PDQ = .empty;
862 var queue: MinHeap = .empty;
860863 defer queue.deinit(gpa);
861864
862865 try queue.push(gpa, 3);
......@@ -878,10 +881,10 @@ test "pop at index" {
878881 try expectEqual(queue.popMin(), null);
879882}
880883
881test "iterator while empty" {
884test "min heap iterator while empty" {
882885 const gpa = std.testing.allocator;
883886
884 var queue: PDQ = .empty;
887 var queue: MinHeap = .empty;
885888 defer queue.deinit(gpa);
886889
887890 var it = queue.iterator();
......@@ -889,10 +892,10 @@ test "iterator while empty" {
889892 try expectEqual(it.next(), null);
890893}
891894
892test "shrinkAndFree" {
895test "min heap shrinkAndFree" {
893896 const gpa = std.testing.allocator;
894897
895 var queue: PDQ = .empty;
898 var queue: MinHeap = .empty;
896899 defer queue.deinit(gpa);
897900
898901 try queue.ensureTotalCapacity(gpa, 4);
......@@ -932,7 +935,7 @@ fn fuzzTestMin(rng: std.Random, comptime queue_size: usize) !void {
932935
933936 const items = try generateRandomSlice(gpa, rng, queue_size);
934937
935 var queue = PDQ.fromOwnedSlice(items, {});
938 var queue: MinHeap = .fromOwnedSlice(items, {});
936939 defer queue.deinit(gpa);
937940
938941 var last_removed: ?u32 = null;
......@@ -962,7 +965,7 @@ fn fuzzTestMax(rng: std.Random, queue_size: usize) !void {
962965
963966 const items = try generateRandomSlice(gpa, rng, queue_size);
964967
965 var queue = PDQ.fromOwnedSlice(items, {});
968 var queue: MinHeap = .fromOwnedSlice(items, {});
966969 defer queue.deinit(gpa);
967970
968971 var last_removed: ?u32 = null;
......@@ -992,7 +995,7 @@ fn fuzzTestMinMax(rng: std.Random, queue_size: usize) !void {
992995
993996 const items = try generateRandomSlice(gpa, rng, queue_size);
994997
995 var queue = PDQ.fromOwnedSlice(items, {});
998 var queue: MinHeap = .fromOwnedSlice(items, {});
996999 defer queue.deinit(gpa);
9971000
9981001 var last_min: ?u32 = null;
......@@ -1032,14 +1035,14 @@ fn contextLessThanComparison(context: []const u32, a: usize, b: usize) Order {
10321035 return std.math.order(context[a], context[b]);
10331036}
10341037
1035const CPDQ = PriorityDequeue(usize, []const u32, contextLessThanComparison);
1038const MinHeapWithContext = PriorityDequeue(usize, []const u32, contextLessThanComparison);
10361039
10371040test "push and pop" {
10381041 const gpa = std.testing.allocator;
10391042
10401043 const context = [_]u32{ 5, 3, 4, 2, 2, 8, 0 };
10411044
1042 var queue: CPDQ = .initContext(context[0..]);
1045 var queue: MinHeapWithContext = .initContext(context[0..]);
10431046 defer queue.deinit(gpa);
10441047
10451048 try queue.push(gpa, 0);