• C# 数据结构 PascalSet


    代码
    #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];
    int result = thisBits[i] & sBits[i];

    // see if result == thisBits[i] - if it doesn't, then not a subset
    if (result != thisBits[i])
    return false;
    }

    return true;
    }

    /// <summary>
    /// Determins if this set is a proper 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 proper subset of the passed-in integers; <b>False</b> otherwise.</returns>
    public virtual bool ProperSubset(params int[] list)
    {
    PascalSet temp
    = new PascalSet(this.lowerBound, this.upperBound, list);
    return ProperSubset(temp);
    }

    /// <summary>
    /// Determins if this set is a proper 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 proper subset of the passed-in characters; <b>False</b> otherwise.</returns>
    public virtual bool ProperSubset(params char[] list)
    {
    int[] intForm = new int[list.Length];
    Array.Copy(list, intForm, list.Length);
    return ProperSubset(intForm);
    }

    /// <summary>
    /// Determins if this set is a proper 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 proper subset of <b>s</b>; <b>False</b> otherwise.</returns>
    public virtual bool ProperSubset(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.");

    return Subset(s) && !s.Subset(this);
    }
    #endregion

    #region Superset
    /// <summary>
    /// Determins if this set is a superset 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 superset of the passed-in integers; <b>False</b> otherwise.</returns>
    public virtual bool Superset(params int[] list)
    {
    PascalSet temp
    = new PascalSet(this.lowerBound, this.upperBound, list);
    return Superset(temp);
    }

    /// <summary>
    /// Determins if this set is a superset 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 superset of the passed-in characters; <b>False</b> otherwise.</returns>
    public virtual bool Superset(params char[] list)
    {
    int[] intForm = new int[list.Length];
    Array.Copy(list, intForm, list.Length);
    return Superset(intForm);
    }

    /// <summary>
    /// Determins if this set is a superset 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 superset of <b>s</b>; <b>False</b> otherwise.</returns>
    public virtual bool Superset(PascalSet s)
    {
    if (!AreSimilar(s))
    throw new ArgumentException("Attempting to compare two dissimilar sets. Superset comparisons can only occur between two sets with the same universe.");

    return s.Subset(this);
    }

    /// <summary>
    /// Determins if this set is a proper superset 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 proper superset of the passed-in integers; <b>False</b> otherwise.</returns>
    public virtual bool ProperSuperset(params int[] list)
    {
    PascalSet temp
    = new PascalSet(this.lowerBound, this.upperBound, list);
    return ProperSuperset(temp);
    }

    /// <summary>
    /// Determins if this set is a proper superset 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 proper superset of the passed-in characters; <b>False</b> otherwise.</returns>
    public virtual bool ProperSuperset(params char[] list)
    {
    int[] intForm = new int[list.Length];
    Array.Copy(list, intForm, list.Length);
    return ProperSuperset(intForm);
    }

    /// <summary>
    /// Determins if this set is a proper superset 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 proper superset of <b>s</b>; <b>False</b> otherwise.</returns>
    public virtual bool ProperSuperset(PascalSet s)
    {
    if (!AreSimilar(s))
    throw new ArgumentException("Attempting to compare two dissimilar sets. Superset comparisons can only occur between two sets with the same universe.");

    return Superset(s) && !s.Superset(this);
    }
    #endregion
    #endregion

    #region PascalSet Properties
    /// <summary>
    /// Returns the lower bound of the set.
    /// </summary>
    public virtual int LowerBound
    {
    get
    {
    return this.lowerBound;
    }
    }

    /// <summary>
    /// Returns the upper bound of the set.
    /// </summary>
    public virtual int UpperBound
    {
    get
    {
    return this.upperBound;
    }
    }
    #endregion

    #region ICloneable Members
    /// <summary>
    /// Clones the PascalSet, performing a deep copy.
    /// </summary>
    /// <returns>A new instance of a PascalSet, using a deep copy.</returns>
    public object Clone()
    {
    PascalSet p
    = new PascalSet(lowerBound, upperBound);
    p.data
    = new BitArray(this.data);
    return p;
    }
    #endregion

    #region ICollection Members

    /// <summary>
    /// Returns a value indicating whether access to the ICollection is synchronized (thread-safe).
    /// </summary>
    public bool IsSynchronized
    {
    get
    {
    return false;
    }
    }

    /// <summary>
    /// Provides the cardinality of the set.
    /// </summary>
    public int Count
    {
    get
    {
    int elements = 0;
    for (int i = 0; i < data.Length; i++)
    if (data.Get(i)) elements++;

    return elements;
    }
    }

    /// <summary>
    /// Copies the elements of the ICollection to an Array, starting at a particular Array index.
    /// </summary>
    public void CopyTo(Array array, int index)
    {
    data.CopyTo(array, index);
    }

    /// <summary>
    /// Returns an object that can be used to synchronize access to the ICollection.
    /// </summary>
    public object SyncRoot
    {
    get
    {
    return this;
    }
    }

    #endregion

    #region IEnumerable Members
    /// <summary>
    /// Returns an IEnumerator to enumerate through the set.
    /// </summary>
    /// <returns>An IEnumerator instance.</returns>
    public IEnumerator GetEnumerator()
    {
    int totalElements = Count;
    int itemsReturned = 0;
    for (int i = 0; i < this.data.Length; i++)
    {
    if (itemsReturned >= totalElements)
    break;
    else if (this.data.Get(i))
    yield return i + this.lowerBound;
    }
    }
    #endregion
    }
    }
  • 相关阅读:
    pip 最新版 发布(Python包安装和管理工具)
    Python使用cookie 免密登录了解一下
    夯实根基,必知必会的 Python 基础知识
    10个关于文件操作的小功能,都很实用~
    总结一些网站加密和混淆技术
    接口加密如何测试?
    艰难的这年,程序员的未来在哪里?
    警惕“职场PUA”!
    Python面试题及答案汇总
    Python实例练手项目汇总(附源码)
  • 原文地址:https://www.cnblogs.com/Googler/p/1752699.html
Copyright © 2020-2023  润新知