LinkedList of T

최승원·2024년 2월 3일

LinkedListOfT.cs

IEnumerable< T > 인터페이스를 상속받는 연결리스트 generic 클래스입니다.

using System;
using System.Collections;
using System.Collections.Generic;

namespace Collections
{
    internal class Node<T>
    {
        public T Value;
        public Node<T> Next;
        public Node<T> Prev;

        public Node(T value) => Value = value; // 생성자. 노드를 만들 때 value 세팅.
    }
    
    internal class LinkedList<T> : IEnumerable<T>
        where T : IComparable<T>
    {
        public Node<T> First => _first;
        public Node<T> Last => _last;

        private Node<T> _first, _last, _tmp;
        
        public void AddFirst(T value)
        {
            _tmp = new Node<T>(value);

            if (_first != null)
            {
                _tmp.Next = _tmp;
                _first.Prev = _tmp;
            }
            else
            {
                _last = _tmp;
            }

            _first = _tmp;
        }

        public void AddLast(T value)
        {
            _tmp = new Node<T>(value);
            
            if (_last != null)
            {
                _last.Next = _tmp;
                _tmp.Prev = _last;
            }
            else
            {
                _first = _tmp;
            }

            _last = _tmp;
        }

        public void AddBefore(Node<T> node, T value)
        {
            _tmp = new Node<T>(value);

            if (node.Prev != null)
            {
                node.Prev.Next = _tmp;
                _tmp.Prev = node.Prev;
            }
            else
            {
                _first = _tmp;
            }

            node.Prev = _tmp;
            _tmp.Next = node;
        }

        public void AddAfter(Node<T> node, T value)
        {
            _tmp = new Node<T>(value);

            if (node.Next != null)
            {
                node.Next.Prev = _tmp;
                _tmp.Next = node.Next;
            }
            else
            {
                _last = _tmp;
            }

            node.Next = _tmp;
            _tmp.Prev = node;
        }

        public Node<T> Find(T target)
        {
            _tmp = _first;
            while (_tmp != null)
            {
                if (Comparer<T>.Default.Compare(_tmp.Value, target) == 0)
                    return _tmp;
                
                _tmp = _tmp.Next;
            }

            return null;
        }
        
        public Node<T> FindLast(T target)
        {
            _tmp = _last;
            while (_tmp != null)
            {
                if (Comparer<T>.Default.Compare(_tmp.Value, target) == 0)
                    return _tmp;
                
                _tmp = _tmp.Prev;
            }

            return null;
        }

        public Node<T> Find(Predicate<T> match)
        {
            _tmp = _first;
            while (_tmp != null)
            {
                if (match.Invoke(_tmp.Value))
                    return _tmp;
                
                _tmp = _tmp.Next;
            }

            return null;
        }
        
        // 마지막부터 시작해서 순회
        public Node<T> FindLast(Predicate<T> match)
        {
            _tmp = _last;
            while (_tmp != null)
            {
                if (match.Invoke(_tmp.Value))
                    return _tmp;
                
                _tmp = _tmp.Prev;
            }

            return null;
        }

        public bool Remove(Node<T> node)
        {
            if (node == null)
                return false;
            
            if (node.Prev != null)
            {
                node.Prev.Next = node.Next;
            }
            else // 삭제하려는 노드가 first일 경우 (이전 노드가 없으므로.)
            {
                _first = node.Next;
            }

            if (node.Next != null)
            {
                node.Next.Prev = node.Prev;
            }
            else // 삭제하려는 노드가 last일 경우 (다음 노드가 없으므로.)
            {
                _last = node.Prev;
            }

            return true;
        }

        public bool Remove(T value)
        {
            return Remove(Find(value));
        }
        public bool Removelast(T value)
        {
            return Remove(FindLast(value));
        }

        public IEnumerator<T> GetEnumerator()
        {
            return new Enumerator(this);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new Enumerator(this);
        }
        
        public struct Enumerator : IEnumerator<T>
        {
            public T Current => _currentNode.Value;
            object IEnumerator.Current => _currentNode.Value;

            private MyLinkedList<T> _linkedList;
            private Node<T> _currentNode;
            
            public Enumerator(MyLinkedList<T> linkedList)
            {
                _linkedList = linkedList;
                _currentNode = null;
            }

            public void Dispose()
            {
                // TODO 관리되는 리소스를 여기에 릴리스
            }

            public bool MoveNext()
            {
                if (_currentNode == null)
                {
                    _currentNode = _linkedList._first;
                }
                else
                {
                    _currentNode = _currentNode.Next;
                }

                return _currentNode != null;
            }

            public void Reset()
            {
                _currentNode = null;
            }
        }
    }
}
profile
안녕하세요. 최승원입니다.

0개의 댓글