Skip to content

Commit 3f7fc0f

Browse files
committed
Fix treap insert to correctly track size on duplicates
insert_node now returns (tree, was_inserted) tuple so that the size counter is only incremented when a new element is actually added. Previously, inserting a duplicate would incorrectly increment size.
1 parent 85263ed commit 3f7fc0f

File tree

1 file changed

+69
-27
lines changed

1 file changed

+69
-27
lines changed

src/treap.rs

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,16 @@ impl<T: Ord> Treap<T> {
8383
}
8484

8585
/// Insert a key with a random priority
86-
pub fn insert<R: Rng>(&mut self, key: T, rng: &mut R) {
86+
///
87+
/// Returns `true` if the key was inserted, `false` if it already existed.
88+
pub fn insert<R: Rng>(&mut self, key: T, rng: &mut R) -> bool {
8789
let priority = rng.random();
88-
self.root = Self::insert_node(self.root.take(), key, priority);
89-
self.size += 1;
90+
let (new_root, inserted) = Self::insert_node(self.root.take(), key, priority);
91+
self.root = new_root;
92+
if inserted {
93+
self.size += 1;
94+
}
95+
inserted
9096
}
9197

9298
/// Check if the treap contains a key
@@ -122,32 +128,39 @@ impl<T: Ord> Treap<T> {
122128
}
123129

124130
// Helper function to insert a node
125-
fn insert_node(node: Option<Box<Node<T>>>, key: T, priority: u32) -> Option<Box<Node<T>>> {
131+
// Returns (new_tree, was_inserted) tuple
132+
fn insert_node(
133+
node: Option<Box<Node<T>>>,
134+
key: T,
135+
priority: u32,
136+
) -> (Option<Box<Node<T>>>, bool) {
126137
match node {
127-
None => Some(Box::new(Node::new(key, priority))),
128-
Some(mut n) => {
129-
match key.cmp(&n.key) {
130-
Ordering::Less => {
131-
n.left = Self::insert_node(n.left, key, priority);
132-
// Maintain heap property
133-
if n.left.as_ref().unwrap().priority > n.priority {
134-
Self::rotate_right(n)
135-
} else {
136-
Some(n)
137-
}
138-
}
139-
Ordering::Greater => {
140-
n.right = Self::insert_node(n.right, key, priority);
141-
// Maintain heap property
142-
if n.right.as_ref().unwrap().priority > n.priority {
143-
Self::rotate_left(n)
144-
} else {
145-
Some(n)
146-
}
147-
}
148-
Ordering::Equal => Some(n), // Key already exists, do nothing
138+
None => (Some(Box::new(Node::new(key, priority))), true),
139+
Some(mut n) => match key.cmp(&n.key) {
140+
Ordering::Less => {
141+
let (new_left, inserted) = Self::insert_node(n.left, key, priority);
142+
n.left = new_left;
143+
// Maintain heap property (only rotate if we actually inserted)
144+
let result = if inserted && n.left.as_ref().unwrap().priority > n.priority {
145+
Self::rotate_right(n)
146+
} else {
147+
Some(n)
148+
};
149+
(result, inserted)
149150
}
150-
}
151+
Ordering::Greater => {
152+
let (new_right, inserted) = Self::insert_node(n.right, key, priority);
153+
n.right = new_right;
154+
// Maintain heap property (only rotate if we actually inserted)
155+
let result = if inserted && n.right.as_ref().unwrap().priority > n.priority {
156+
Self::rotate_left(n)
157+
} else {
158+
Some(n)
159+
};
160+
(result, inserted)
161+
}
162+
Ordering::Equal => (Some(n), false), // Key already exists, do nothing
163+
},
151164
}
152165
}
153166

@@ -310,4 +323,33 @@ mod tests {
310323
}
311324
}
312325
}
326+
327+
#[test]
328+
fn test_duplicate_insertion() {
329+
let mut treap = Treap::new();
330+
let mut rng = StdRng::seed_from_u64(42);
331+
332+
// Insert elements
333+
assert!(treap.insert(5, &mut rng)); // First insertion returns true
334+
assert!(treap.insert(3, &mut rng));
335+
assert!(treap.insert(7, &mut rng));
336+
assert_eq!(treap.len(), 3);
337+
338+
// Try to insert duplicates - should return false and not change size
339+
assert!(!treap.insert(5, &mut rng));
340+
assert!(!treap.insert(3, &mut rng));
341+
assert!(!treap.insert(7, &mut rng));
342+
assert_eq!(treap.len(), 3); // Size unchanged
343+
344+
// Verify elements still exist
345+
assert!(treap.contains(&5));
346+
assert!(treap.contains(&3));
347+
assert!(treap.contains(&7));
348+
349+
// Remove and re-insert should work
350+
assert!(treap.remove(&5));
351+
assert_eq!(treap.len(), 2);
352+
assert!(treap.insert(5, &mut rng)); // Re-insertion returns true
353+
assert_eq!(treap.len(), 3);
354+
}
313355
}

0 commit comments

Comments
 (0)