zoukankan      html  css  js  c++  java
  • 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
    }
    }
  • 相关阅读:
    Flutter form 的表单 input
    FloatingActionButton 实现类似 闲鱼 App 底部导航凸起按钮
    Flutter 中的常见的按钮组件 以及自 定义按钮组件
    Drawer 侧边栏、以及侧边栏内 容布局
    AppBar 自定义顶部导航按钮 图标、颜色 以及 TabBar 定义顶部 Tab 切换 通过TabController 定义TabBar
    清空路由 路由替换 返回到根路由
    应对ubuntu linux图形界面卡住的方法
    [转] 一块赚零花钱
    [转]在树莓派上搭建LAMP服务
    ssh保持连接
  • 原文地址:https://www.cnblogs.com/Googler/p/1752699.html
Copyright © 2011-2022 走看看