现在的位置: 首页 > 综合 > 正文

C# 数据结构 PascalSet

2012年11月26日 ⁄ 综合 ⁄ 共 10111字 ⁄ 字号 评论关闭

 

代码

#region Using directives

using System;
using System.Collections;
using System.Text;

#endregion

namespace SkmDataStructures2
{
public class PascalSet : ICloneable, ICollection, IEnumerable
{
// Private member variables
private int lowerBound, upperBound;
private BitArray data;

#region Constructors
/// <summary>
/// Creates a new PascalSet instance with a specified lower and upper bound.
/// </summary>
/// <param name="lowerBound">The lower bound for the set. Can be any legal character value.</param>
/// <param name="upperBound">The upper bound for the set. Can be any legal character value.</param>
public PascalSet(char lowerBound, char upperBound) : this((int) lowerBound, (int) upperBound) { }

/// <summary>
/// Creates a new PascalSet instance with a specified lower and upper bound.
/// </summary>
/// <param name="lowerBound">The lower bound for the set. Can be any legal integer value.</param>
/// <param name="upperBound">The upper bound for the set. Can be any legal integer value.</param>
public PascalSet(int lowerBound, int upperBound)
{
// make sure lowerbound is less than or equal to upperbound
if (lowerBound > upperBound)
throw new ArgumentException("The set's lower bound cannot be greater than its upper bound.");

this.lowerBound = lowerBound;
this.upperBound = upperBound;

// Create the BitArray
data = new BitArray(upperBound - lowerBound + 1);
}

/// <summary>
/// Creates a new PascalSet instance whose initial values are assigned from an integer array.
/// </summary>
/// <param name="lowerBound">The lower bound for the set. Can be any legal integer value.</param>
/// <param name="upperBound">The upper bound for the set. Can be any legal integer value.</param>
/// <param name="initialData">An integer array that is used as the initial values of the array.</param>
public PascalSet(int lowerBound, int upperBound, int[] initialData)
{
// make sure lowerbound is less than or equal to upperbound
if (lowerBound > upperBound)
throw new ArgumentException("The set's lower bound cannot be greater than its upper bound.");

this.lowerBound = lowerBound;
this.upperBound = upperBound;

// Create the BitArray
data = new BitArray(upperBound - lowerBound + 1);

// Populuate the BitArray with the passed-in initialData array.
for (int i = 0; i < initialData.Length; i++)
{
int val = initialData[i];
if (val >= this.lowerBound && val <= this.upperBound)
data.Set(val
- this.lowerBound, true);
else
throw new ArgumentException("Attempting to add an element with value " + val.ToString() + " that is outside of the set's universe. Value must be between " + this.lowerBound.ToString() + " and " + this.upperBound.ToString());
}
}
#endregion

#region Methods
/// <summary>
/// Determines if two PascalSets are "compatible." Specifically, it checks to ensure that the PascalSets
/// share the same lower and upper bounds.
/// <returns><b>True</b> if the PascalSets share the same bounds, <b>False</b> otherwise.</returns>
protected virtual bool AreSimilar(PascalSet s)
{
return this.lowerBound == s.lowerBound && this.upperBound == s.upperBound;
}

#region Union
/// <summary>
/// Unions a set of integers with the current PascalSet.
/// </summary>
/// <param name="list">An variable number of integers.</param>
/// <returns>A new PascalSet, which is the union of the <b>this</b> PascalSet and the passed-in integers.</returns>
public virtual PascalSet Union(params int[] list)
{
// create a deep copy of this
PascalSet result = (PascalSet)Clone();

// For each integer passed in, if it's within the bounds add it to the results's BitArray.
for (int i = 0; i < list.Length; i++)
{
int val = list[i];
if (val >= this.lowerBound && val <= this.upperBound)
result.data.Set(val
- this.lowerBound, true);
else
throw new ArgumentException("Attempting to add an element with value " + val.ToString() + " that is outside of the set's universe. Value must be between " + this.lowerBound.ToString() + " and " + this.upperBound.ToString());
}

return result; // return the new PascalSet
}

/// <summary>
/// Unions a set of characters with the current PascalSet.
/// </summary>
/// <param name="list">A variable number of characters.</param>
/// <returns>A new PascalSet, which is the union of the <b>this</b> PascalSet and the passed-in characters.</returns>
public virtual PascalSet Union(params char[] list)
{
int[] intForm = new int[list.Length];
Array.Copy(list, intForm, list.Length);
return Union(intForm);
}

/// <summary>
/// Unions a passed-in PascalSet with the current PascalSet.
/// </summary>
/// <param name="s">A PascalSet.</param>
/// <returns>A new PascalSet whose elements are the union of <b>s</b> and <b>this</b>.</returns>
/// <remarks><b>s</b> and <b>this</b> must be "similar" PascalSets.</remarks>
public virtual PascalSet Union(PascalSet s)
{
if (!AreSimilar(s))
throw new ArgumentException("Attempting to union two dissimilar sets. Union can only occur between two sets with the same universe.");

// do a bit-wise OR to union together this.data and s.data
PascalSet result = (PascalSet)Clone();
result.data.Or(s.data);

return result;
}

// Overloaded + operator for union...
public static PascalSet operator +(PascalSet s, PascalSet t)
{
return s.Union(t);
}
#endregion

#region Intersection
/// <summary>
/// Intersects a set of integers with the current PascalSet.
/// </summary>
/// <param name="list">An variable number of integers.</param>
/// <returns>A new PascalSet, which is the intersection of the <b>this</b> PascalSet and the passed-in integers.</returns>
public virtual PascalSet Intersection(params int[] list)
{
PascalSet result
= new PascalSet(this.lowerBound, this.upperBound);

for (int i = 0; i < list.Length; i++)
{
// only add the element to result if its in this.data
int val = list[i];
if (val >= this.lowerBound && val <= this.upperBound)
if (this.data.Get(val - this.lowerBound))
result.data.Set(val
- this.lowerBound, true);
}

return result;
}

/// <summary>
/// Intersects a set of characters with the current PascalSet.
/// </summary>
/// <param name="list">A variable number of characters.</param>
/// <returns>A new PascalSet, which is the intersection of the <b>this</b> PascalSet and the passed-in characters.</returns>
public virtual PascalSet Intersection(params char[] list)
{
int[] intForm = new int[list.Length];
Array.Copy(list, intForm, list.Length);
return Intersection(intForm);
}

/// <summary>
/// Intersects a passed-in PascalSet with the current PascalSet.
/// </summary>
/// <param name="s">A PascalSet.</param>
/// <returns>A new PascalSet whose elements are the intersection of <b>s</b> and <b>this</b>.</returns>
/// <remarks><b>s</b> and <b>this</b> must be "similar" PascalSets.</remarks>
public virtual PascalSet Intersection(PascalSet s)
{
if (!AreSimilar(s))
throw new ArgumentException("Attempting to intersect two dissimilar sets. Intersection can only occur between two sets with the same universe.");

// do a bit-wise AND to intersect this.data and s.data
PascalSet result = (PascalSet)Clone();
result.data.And(s.data);

return result;
}

// Overloaded * operator for intersection
public static PascalSet operator *(PascalSet s, PascalSet t)
{
return s.Intersection(t);
}
#endregion

#region Difference
/// <summary>
/// Set differences a set of integers with the current PascalSet.
/// </summary>
/// <param name="list">An variable number of integers.</param>
/// <returns>A new PascalSet, which is the set difference of the <b>this</b> PascalSet and the passed-in integers.</returns>
public virtual PascalSet Difference(params int[] list)
{
PascalSet result
= new PascalSet(this.lowerBound, this.upperBound, list);
return Difference(result);
}

/// <summary>
/// Set differences a set of characters with the current PascalSet.
/// </summary>
/// <param name="list">A variable number of characters.</param>
/// <returns>A new PascalSet, which is the set difference of the <b>this</b> PascalSet and the passed-in characters.</returns>
public virtual PascalSet Difference(params char[] list)
{
int[] intForm = new int[list.Length];
Array.Copy(list, intForm, list.Length);
return Difference(intForm);
}

/// <summary>
/// Set differences a passed-in PascalSet with the current PascalSet.
/// </summary>
/// <param name="s">A PascalSet.</param>
/// <returns>A new PascalSet whose elements are the set difference of <b>s</b> and <b>this</b>.</returns>
/// <remarks><b>s</b> and <b>this</b> must be "similar" PascalSets.</remarks>
public virtual PascalSet Difference(PascalSet s)
{
if (!AreSimilar(s))
throw new ArgumentException("Attempting to apply set difference to two dissimilar sets. Set difference can only occur between two sets with the same universe.");

// do a bit-wise XOR and then an AND to achieve set difference
PascalSet result = (PascalSet)Clone();
result.data.Xor(s.data).And(
this.data);

return result;
}

// Overloaded - operator for set difference
public static PascalSet operator -(PascalSet s, PascalSet t)
{
return s.Difference(t);
}
#endregion

#region Complement
/// <summary>
/// Complements a PascalSet.
/// </summary>
/// <returns>A new PascalSet that is the complement of <b>this</b>.</returns>
public virtual PascalSet Complement()
{
PascalSet result
= (PascalSet)Clone();
result.data.Not();
return result;
}
#endregion

#region Element Of
/// <summary>
/// Determines if a passed-in value is an element of the PascalSet.
/// </summary>
/// <param name="x">The integer to check if it exists in the set.</param>
/// <returns><b>True</b> is <b>x</b> is in the set, <b>False</b> otherwise</returns>
public virtual bool ContainsElement(int x)
{
if (x < lowerBound || x > upperBound)
return false;

return this.data.Get(x - lowerBound);
}

/// <summary>
/// Determines if a passed-in value is an element of the PascalSet.
/// </summary>
/// <param name="x">The character to check if it exists in the set.</param>
/// <returns><b>True</b> is <b>x</b> is in the set, <b>False</b> otherwise</returns>
public virtual bool ContainsElement(char x)
{
return ContainsElement((int)x);
}
#endregion

#region Subset
/// <summary>
/// Determins if this set is a subset of the integers passed-in.
/// </summary>
/// <param name="list">A variable number of integers.</param>
/// <returns><b>True</b> if <b>this</b> is a subset of the passed-in integers; <b>False</b> otherwise.</returns>
public virtual bool Subset(params int[] list)
{
PascalSet temp
= new PascalSet(this.lowerBound, this.upperBound, list);
return Subset(temp);
}

/// <summary>
/// Determins if this set is a subset of the characters passed-in.
/// </summary>
/// <param name="list">A variable number of characters.</param>
/// <returns><b>True</b> if <b>this</b> is a subset of the passed-in characters; <b>False</b> otherwise.</returns>
public virtual bool Subset(params char[] list)
{
int[] intForm = new int[list.Length];
Array.Copy(list, intForm, list.Length);
return Subset(intForm);
}

/// <summary>
/// Determins if this set is a subset of the passed-in PascalSet.
/// </summary>
/// <param name="s">A PascalSet that is "similar" to <b>this</b>.</param>
/// <returns><b>True</b> if <b>this</b> is a subset of <b>s</b>; <b>False</b> otherwise.</returns>
public virtual bool Subset(PascalSet s)
{
if (!AreSimilar(s))
throw new ArgumentException("Attempting to compare two dissimilar sets. Subset comparisons can only occur between two sets with the same universe.");

// Get the BitArray's underlying array
const int INT_SIZE = 32;
int arraySize = (data.Length + INT_SIZE - 1) / INT_SIZE;
int[] thisBits = new int[arraySize];
int[] sBits = new int[arraySize];
data.CopyTo(thisBits,
0);
s.data.CopyTo(sBits,
0);

// now, enumerate through the int array elements
for (int i = 0; i < thisBits.Length; i++)
{
// do a bitwise AND between thisBits[i] and sBits[i];

抱歉!评论已关闭.