algorithms(avl): add changes

Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
Matej Focko 2024-01-31 18:55:18 +01:00
parent f46561653f
commit aa6f33feb5
Signed by: mfocko
GPG key ID: 7C47D46246790496
4 changed files with 154 additions and 18 deletions

View file

@ -1,6 +1,6 @@
using System.Collections; using System.Collections;
namespace avl; namespace AVL;
class AVL<T>(IComparer<T> comparator) : IEnumerable<T> { class AVL<T>(IComparer<T> comparator) : IEnumerable<T> {
private Node<T>? _root = null; private Node<T>? _root = null;
@ -10,11 +10,87 @@ class AVL<T>(IComparer<T> comparator) : IEnumerable<T> {
public int Count { get; private set; } = 0; public int Count { get; private set; } = 0;
public IComparer<T> Comparator { get; } = comparator; public IComparer<T> Comparator { get; } = comparator;
#region AVLSpecific
private static (bool correct, int depth) Check(Node<T>? node, int depth) {
if (node == null) {
return (true, depth);
}
var (leftCorrect, leftDepth) = Check(node.Left, 1 + depth);
if (!leftCorrect) {
return (false, leftDepth);
}
var (rightCorrect, rightDepth) = Check(node.Right, 1 + depth);
var foundDepth = Math.Max(leftDepth, rightDepth);
return (rightCorrect && Math.Abs(leftDepth - rightDepth) <= 1, foundDepth);
}
public bool IsCorrect() {
var (correct, _) = Check(_root, 0);
return correct;
}
private void InsertRebalance(List<Node<T>> nodes) {
// TODO
}
private void DeleteRebalance(List<Node<T>> nodes) {
// TODO
}
#endregion
public bool Add(T item) { public bool Add(T item) {
throw new NotImplementedException(); int cmp;
// insert the node
var path = new List<Node<T>>();
var node = _root;
while (node != null) {
path.Add(node);
cmp = Comparator.Compare(node.Value, item);
if (cmp < 0) {
node = node.Right;
} else if (cmp == 0) {
return false;
} else {
node = node.Left;
}
}
var newItem = new Node<T>(item);
++Count;
// adding root
if (path.Count == 0) {
_root = newItem;
return true;
}
var lastIdx = path.Count - 1;
cmp = Comparator.Compare(path[lastIdx].Value, item);
if (cmp < 0) {
path[lastIdx].Right = newItem;
} else {
path[lastIdx].Left = newItem;
}
path.Add(newItem);
// rebalance
InsertRebalance(path);
return true;
} }
public bool Remove(T item) { public bool Remove(T item) {
// delete the node
// rebalance
throw new NotImplementedException(); throw new NotImplementedException();
} }

View file

@ -1,10 +1,16 @@
namespace avl; namespace AVL;
enum NodeType {
Minus,
Zero,
Plus,
}
class Node<T> { class Node<T> {
public T Value { get; init; } public T Value { get; init; }
public readonly Node<T>? Parent; public Node<T>? Left = null, Right = null;
public readonly Node<T>? Left, Right; public NodeType Type = NodeType.Zero;
public Node(T value) { public Node(T value) {
Value = value; Value = value;

View file

@ -1,4 +1,4 @@
namespace avl.test; namespace AVL.Test;
public class AVL { public class AVL {
[Fact] [Fact]
@ -8,8 +8,10 @@ public class AVL {
Assert.Equal(0, t.Count); Assert.Equal(0, t.Count);
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
Assert.False(t.Contains(i)); Assert.False(t.Contains(i), $"Empty tree should not contain {i}");
} }
Assert.True(t.IsCorrect(), "AVL invariants hold for an empty tree");
} }
[Fact] [Fact]
@ -19,6 +21,66 @@ public class AVL {
}; };
Assert.Equal(1, t.Count); Assert.Equal(1, t.Count);
Assert.True(t.Contains(1)); Assert.True(t.Contains(123), "Tree contains the added element 123");
Assert.True(t.IsCorrect(), "AVL invariants hold");
}
[Fact]
public void TwoNodes() {
var t = new AVL<int> {
1, 2
};
Assert.Equal(2, t.Count);
Assert.True(t.Contains(1), "Tree contains the added element 1");
Assert.True(t.Contains(2), "Tree contains the added element 2");
Assert.True(t.IsCorrect(), "AVL invariants hold");
}
[Fact]
public void TwoNodesReversed() {
var t = new AVL<int> {
2, 1
};
Assert.Equal(2, t.Count);
Assert.True(t.Contains(1), "Tree contains the added element 1");
Assert.True(t.Contains(2), "Tree contains the added element 2");
Assert.True(t.IsCorrect(), "AVL invariants hold");
}
[Fact]
public void ThreeNodes() {
var t = new AVL<int> {
1, 2, 3
};
Assert.Equal(3, t.Count);
Assert.True(t.Contains(1), "Tree contains the added element 1");
Assert.True(t.Contains(2), "Tree contains the added element 2");
Assert.True(t.Contains(3), "Tree contains the added element 3");
Assert.True(t.IsCorrect(), "AVL invariants hold");
}
[Fact]
public void BiggerTree() {
var t = new AVL<int>();
for (int i = -10; i <= 10; ++i) {
t.Add(i);
}
Assert.Equal(21, t.Count);
for (int i = -100; i <= 100; ++i) {
Assert.Equal(-10 <= i && i <= 10, t.Contains(i));
}
Assert.True(t.IsCorrect(), "AVL invariants hold");
} }
} }

View file

@ -1,8 +0,0 @@
namespace avl.test;
public class Node {
[Fact]
public void Test1() {
}
}