using System;
using System.Collections.Generic;
namespace Collections
{
///
/// ソート済み配列。
///
/// 要素の型
///
/// 2分探索できるので、検索は O(log n)。
/// ソート済みの状態を保つため、要素の挿入・削除には O(n) 必要。
///
class SortedArray : ISet
where T: IComparable
{
#region フィールド
ArrayList buffer;
#endregion
#region 初期化
public SortedArray() : this(256) { }
public SortedArray(int capacity)
{
this.buffer = new ArrayList(capacity);
}
#endregion
#region 要素の挿入・削除・検索
///
/// 要素の挿入。
///
/// 挿入する要素
public void Insert(T elem)
{
if (this.buffer.Count == 0)
{
this.buffer.InsertLast(elem);
return;
}
int r = this.buffer.Count - 1;
int l = 0;
int comp;
while (l < r)
{
int m = (r + l) >> 1;
comp = this.buffer[m].CompareTo(elem);
if (comp > 0) r = m - 1;
else if (comp < 0) l = m + 1;
else return; // 重複不可
}
comp = this.buffer[l].CompareTo(elem);
if(comp < 0)
this.buffer.Insert(l + 1, elem);
else if(comp > 0)
this.buffer.Insert(l, elem);
}
///
/// 要素の検索。
///
/// 検索する要素
/// 要素の位置(見つからなかった場合、配列長)
public int IndexOf(T elem)
{
if (this.buffer.Count == 0)
return 0;
int r = this.buffer.Count - 1;
int l = 0;
while (l < r)
{
int m = (r + l) >> 1;
int comp = this.buffer[m].CompareTo(elem);
if (comp > 0) r = m - 1;
else if (comp < 0) l = m + 1;
else return m;
}
if(this.buffer[l].CompareTo(elem) == 0)
return l;
return this.buffer.Count;
}
///
/// テーブル中に要素が含まれているかどうか判別。
///
/// 探したい要素
/// 含まれていれば true
public bool Contains(T elem)
{
return this.IndexOf(elem) != this.buffer.Count;
}
///
/// テーブル中の要素を検索。
///
/// 探したい要素
/// 含まれていればその要素を、なければ default(T)
public T Find(T elem)
{
int i = this.IndexOf(elem);
if (i == this.buffer.Count)
return default(T);
return this.buffer[i];
}
///
/// 要素の削除。
///
/// 削除する要素
public void Erase(T elem)
{
int i = this.IndexOf(elem);
if (i < this.buffer.Count)
this.buffer.Erase(i);
}
#endregion
#region IEnumerable メンバ
public IEnumerator GetEnumerator()
{
for (int i = 0; i < this.buffer.Count; ++i)
yield return this.buffer[i];
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
}
}