예제 #1
0
        public override T?Find(T targetValue)
        {
            SafeNode <T> current = Root;

            current?.Mtx.WaitOne();
            if (current?.Value.CompareTo(targetValue) == 0)
            {
                current.Mtx.ReleaseMutex();
                return(targetValue);
            }

            while (current != null)
            {
                if (current.Value.CompareTo(targetValue) < 0)
                {
                    current.Right?.Mtx.WaitOne();
                    current.Mtx.ReleaseMutex();
                    current = current.Right;
                }
                else if (current.Value.CompareTo(targetValue) > 0)
                {
                    current.Left?.Mtx.WaitOne();
                    current.Mtx.ReleaseMutex();
                    current = current.Left;
                }
                else
                {
                    current.Mtx.ReleaseMutex();
                    return(targetValue);
                }
            }

            return(null);
        }
예제 #2
0
        public override void Insert(T value)
        {
            SafeNode <T> current = Root;
            SafeNode <T> newNode = new SafeNode <T>(value);

            _mtxRoot.WaitOne();
            if (Root == null)
            {
                Root = newNode;
                _mtxRoot.ReleaseMutex();
                return;
            }
            _mtxRoot.ReleaseMutex();
            current?.Mtx.WaitOne();

            while (true)
            {
                if (current?.Value.CompareTo(newNode.Value) < 0)
                {
                    if (current.Right == null)
                    {
                        current.Right = newNode;
                        current.Mtx.ReleaseMutex();
                        break;
                    }
                    current.Right?.Mtx.WaitOne();
                    current.Mtx.ReleaseMutex();
                    current = current.Right;
                }
                else if (current?.Value.CompareTo(newNode.Value) > 0)
                {
                    if (current.Left == null)
                    {
                        current.Left = newNode;
                        current.Mtx.ReleaseMutex();
                        break;
                    }
                    current.Left?.Mtx.WaitOne();
                    current.Mtx.ReleaseMutex();
                    current = current.Left;
                }
                else
                {
                    current?.Mtx.ReleaseMutex();
                    break;
                }
            }
        }
예제 #3
0
        public override void Remove(T targetValue)
        {
            // Find target node to remove
            SafeNode <T> current        = Root;
            SafeNode <T> target         = null;
            SafeNode <T> parentOfTarget = null;

            current?.Mtx.WaitOne();
            if (current?.Value.CompareTo(targetValue) == 0)
            {
                target = current;
            }
            else
            {
                while (current != null)
                {
                    if (current.Value.CompareTo(targetValue) < 0)
                    {
                        current.Right?.Mtx.WaitOne();
                        current.Mtx.ReleaseMutex();
                        parentOfTarget = current;
                        current        = current.Right;
                    }
                    else if (current.Value.CompareTo(targetValue) > 0)
                    {
                        current.Left?.Mtx.WaitOne();
                        current.Mtx.ReleaseMutex();
                        parentOfTarget = current;
                        current        = current.Left;
                    }
                    else
                    {
                        target = current;
                        break;
                    }
                }
            }

            if (target == null)
            {
                return;
            }

            // Find nearest neighbors from left and right subtrees
            SafeNode <T> leftNeighbor       = target.Left;
            SafeNode <T> prevOfLeftNeighbor = target;

            leftNeighbor?.Mtx.WaitOne();
            SafeNode <T> rightNeighbor       = target.Right;
            SafeNode <T> prevOfRightNeighbor = target;

            rightNeighbor?.Mtx.WaitOne();
            while (leftNeighbor?.Right != null || rightNeighbor?.Left != null)
            {
                leftNeighbor?.Right?.Mtx.WaitOne();
                if (leftNeighbor?.Right != null)
                {
                    leftNeighbor?.Mtx.ReleaseMutex();
                    prevOfLeftNeighbor = leftNeighbor;
                    leftNeighbor       = leftNeighbor?.Right;
                }

                rightNeighbor?.Left?.Mtx.WaitOne();
                if (rightNeighbor?.Left != null)
                {
                    rightNeighbor?.Mtx.ReleaseMutex();
                    prevOfRightNeighbor = rightNeighbor;
                    rightNeighbor       = rightNeighbor?.Left;
                }
            }

            // Target node is leaf, just delete it
            if (leftNeighbor == null && rightNeighbor == null)
            {
                if (parentOfTarget?.Left?.Equals(target) == true)
                {
                    parentOfTarget.Left = null;
                }
                else if (parentOfTarget?.Right?.Equals(target) == true)
                {
                    parentOfTarget.Right = null;
                }
                else
                {
                    Root = null;
                }
                target.Mtx.ReleaseMutex();
                return;
            }

            // Otherwise, swap values with one of nearest neighbors in subtrees
            if (leftNeighbor != null)
            {
                target.Value = leftNeighbor.Value;
                if (prevOfLeftNeighbor.Equals(target))
                {
                    target.Left = leftNeighbor.Left;
                }
                else
                {
                    prevOfLeftNeighbor.Right = leftNeighbor.Left;
                }
            }
            else
            {
                target.Value = rightNeighbor.Value;
                if (prevOfRightNeighbor.Equals(target))
                {
                    target.Right = rightNeighbor.Right;
                }
                else
                {
                    prevOfRightNeighbor.Left = rightNeighbor.Right;
                }
            }
            leftNeighbor?.Mtx.ReleaseMutex();
            rightNeighbor?.Mtx.ReleaseMutex();
            target.Mtx.ReleaseMutex();
        }
예제 #4
0
 public SafeNode(T value) : base(value)
 {
     Mtx   = new Mutex();
     Left  = null;
     Right = null;
 }