MitoshiroPJ
1/13/2019 - 11:54 AM

条件付き除外とかができたりするコレクション

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class MtLinkedList<t> : IEnumerable<t>
{
    private const int createNum = 16; // ノードを作成する際の個数
    private MtLinkedListNode first;   // リンクリストの先頭
    private MtLinkedListNode last;    // リンクリストの末尾
    private MtLinkedListNode pool;    // 未使用ノードのプール(先頭)
    private int count;                // ノード数

    // ノード数
    public int Count
    {
        get { return count; }
    }

    // リンクリストのノードクラス
    public class MtLinkedListNode
    {
        public T Value;
        public MtLinkedListNode Next;
    }

    // 反復子クラス
    public class MtLinkedListEnumerator : IEnumerator<t>, IDisposable
    {
        private MtLinkedListNode cur;
        private MtLinkedListNode first;
        public MtLinkedListEnumerator(MtLinkedListNode first)
        {
            this.first = first;
        }
        public void Dispose()
        {
        }

        public T Current
        {
            get { return cur.Value; }
        }

        object IEnumerator.Current
        {
            get { return cur.Value; }
        }

        bool IEnumerator.MoveNext()
        {
            if (first == null) { return false; }
            if (cur == null) { cur = first; return true; }
            cur = cur.Next;
            return (cur != null);
        }
        void IEnumerator.Reset()
        {
            cur = first;
        }
    }

    // IEnumerable実装
    public IEnumerator<t> GetEnumerator()
    {
        return new MtLinkedListEnumerator(first);
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return new MtLinkedListEnumerator(first);
    }

    // コンストラクタ
    public MtLinkedList()
    {
        first = null;
        last = null;
        pool = null;
        count = 0;
    }
    public MtLinkedList(int cap)
    {
        first = null;
        last = null;
        pool = null;
        count = 0;
        createNode(cap);
    }

    // 追加
    public void Add(T val)
    {
        MtLinkedListNode node = getNode();
        if( first == null )
        {
            first = node;
        }
        if( last == null )
        {
            last = node;
        }
        else
        {
            last.Next = node;
            last = node;
        }
        node.Value = val;
        count += 1;
    }

    // 反復処理
    public void EachDo(Action<t> act)
    {
        MtLinkedListNode cur = first;
        while (cur != null)
        {
            act(cur.Value);
            cur = cur.Next;
        }
    }

    // 条件付き反復処理
    public void EachDo(Predicate<t> pred, Action<t> act)
    {
        MtLinkedListNode cur = first;
        while (cur != null)
        {
            if (pred(cur.Value))
            {
                act(cur.Value);
            }
            cur = cur.Next;
        }
    }

    // 反復処理後、条件を満たしていれば削除
    public void EachDoAndRemove(Action<t> act, Predicate<t> pred, Action<t> finalizer)
    {
        MtLinkedListNode prev = null;
        MtLinkedListNode cur = first;
        while( cur != null )
        {
            act(cur.Value);
            MtLinkedListNode next = cur.Next;

            if (pred(cur.Value))
            {
                finalizer(cur.Value);
                if (prev == null)
                {
                    first = cur.Next;
                }
                else
                {
                    prev.Next = cur.Next;
                }
                if (last == cur)
                {
                    last = prev;
                }
                cur.Next = pool;
                pool = cur;
                count -= 1;
            }
            else
            {
                prev = cur;
            }
            cur = next;
        }
    }

    // 条件を満たしていれば削除
    public void EachRemove(Predicate<t> pred, Action<t> finalizer)
    {
        EachDoAndRemove(e => { }, pred, finalizer);
    }

    // 新規ノードをプールから取得
    private MtLinkedListNode getNode()
    {
        if (pool == null)
        {
            createNode(createNum);
        }
        MtLinkedListNode node = pool;
        pool = pool.Next;
        node.Next = null;
        node.Value = default(T);
        return node;
    }

    // ノードを作成し、プールに置く
    private void createNode(int num)
    {
        for( int t=0; t< num; t++ )
        {
            MtLinkedListNode node = new MtLinkedListNode();
            if( pool == null )
            {
                pool = node;
            }
            else
            {
                node.Next = pool;
                pool = node;
            }
        }
    }
}