173 lines
3.8 KiB
C#
173 lines
3.8 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Global.Shared.OcTree
|
|
{
|
|
public interface IImmutableBag<E> : IEnumerable<E>
|
|
{
|
|
/// <summary>Returns the element at the specified position in Bag</summary>
|
|
/// <param name="index">the index of the element to return</param>
|
|
/// <returns>the element at the specified position in bag</returns>
|
|
E Get(int index);
|
|
|
|
/// <summary>Returns the number of elements in this Bag</summary>
|
|
/// <returns>the number of elements in this bag</returns>
|
|
int Size();
|
|
|
|
bool IsEmpty();
|
|
|
|
bool Contains(E element);
|
|
}
|
|
|
|
public class Bag<E> : IImmutableBag<E>
|
|
{
|
|
public E[] data;
|
|
private BagEnumerator it;
|
|
protected int size;
|
|
|
|
public Bag() : this(64)
|
|
{
|
|
}
|
|
|
|
public Bag(int capacity)
|
|
{
|
|
data = new E[capacity];
|
|
}
|
|
|
|
public E this[int i]
|
|
{
|
|
get => Get(i);
|
|
set => data[i] = value;
|
|
}
|
|
|
|
public E Get(int index)
|
|
{
|
|
return data[index];
|
|
}
|
|
|
|
/// <summary>Returns the number of elements in this Bag</summary>
|
|
/// <returns>the number of elements in this bag</returns>
|
|
public int Size()
|
|
{
|
|
return size;
|
|
}
|
|
|
|
public bool IsEmpty()
|
|
{
|
|
return size == 0;
|
|
}
|
|
|
|
public bool Contains(E e)
|
|
{
|
|
for (var i = 0; i < size; i++)
|
|
{
|
|
var e2 = data[i];
|
|
|
|
if (!e.Equals(e2)) return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public E Remove(int index)
|
|
{
|
|
var e = data[index];
|
|
data[index] = data[--size];
|
|
data[size] = default;
|
|
return e;
|
|
}
|
|
|
|
public E RemoveLast()
|
|
{
|
|
if (IsEmpty()) return default;
|
|
|
|
var e = data[--size];
|
|
data[size] = default;
|
|
return e;
|
|
}
|
|
|
|
public bool Remove(E e)
|
|
{
|
|
for (var i = 0; i < size; i++)
|
|
{
|
|
var e2 = data[i];
|
|
|
|
if (!e.Equals(e2)) continue;
|
|
|
|
data[i] = data[--size];
|
|
data[size] = default;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>Returns the number of elements this bag can hold without growing.</summary>
|
|
/// <returns>the number of elements this bag can hold without growing</returns>
|
|
public int Capacity()
|
|
{
|
|
return data.Length;
|
|
}
|
|
|
|
public void Add(E e)
|
|
{
|
|
if (size == data.Length) Grow(data.Length + 1);
|
|
|
|
data[size++] = e;
|
|
}
|
|
|
|
public void Grow(int newCapacity)
|
|
{
|
|
Array.Resize(ref data, newCapacity);
|
|
}
|
|
|
|
#region Enumerator
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return GetEnumerator();
|
|
}
|
|
|
|
public IEnumerator<E> GetEnumerator()
|
|
{
|
|
if (it == null) it = new BagEnumerator(this);
|
|
|
|
it.Cursor = -1;
|
|
|
|
return it;
|
|
}
|
|
|
|
public class BagEnumerator : IEnumerator<E>
|
|
{
|
|
private readonly Bag<E> bag;
|
|
internal int Cursor;
|
|
|
|
public BagEnumerator(Bag<E> bag)
|
|
{
|
|
this.bag = bag;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
|
|
public bool MoveNext()
|
|
{
|
|
Cursor++;
|
|
return Cursor < bag.size;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
Cursor = -1;
|
|
}
|
|
|
|
object IEnumerator.Current => Current;
|
|
|
|
public E Current => bag.data[Cursor];
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |