import java.util.ArrayList; import java.util.Iterator; /* An instance of this class represents a set of integers. ** ** Author: R. McCloskey ** Date: April 2020 */ public class SetOfInt { // instance variables // ------------------ // The members of the set are the elements of this ArrayList, // arranged in increasing order. private ArrayList members; // constructor // ----------- /* Initializes this to be an empty set. */ public SetOfInt() { members = new ArrayList(); } /* Initializes this to be the set containing the ** values in the given ArrayList. ** pre: The values in the given ArrayList are distinct and in ** increasing order. */ protected SetOfInt(ArrayList mems) { members = (ArrayList)(mems.clone()); } // observers // --------- /* Reports whether or not the given integer is a member of this set. */ public boolean isMember(int m) { int k = binarySearch(m); return k != members.size() && members.get(k) == m; } /* Returns the number of members in this set. */ public int cardinality() { return members.size(); } /* Reports whether this set is empty. */ public boolean isEmpty() { return cardinality() == 0; } @Override public String toString() { return members.toString(); } // mutators // -------- /* Ensures that the given integer is a member of this set, ** inserting it if necessary. */ public void insert(int m) { int k = binarySearch(m); if (k == members.size()) { members.add(m); } else if (members.get(k) != m) { members.add(k, m); } else { // do nothing, as m is already a member } } /* Ensures that the given integer is not a member of this set, ** removing it if necessary. */ public void remove(int m) { int k = binarySearch(m); if (k != members.size() && members.get(k) == m) { members.remove(k); } else { // do nothing, as m is not a member } } // generators // ---------- /* Returns an iterator that iterates over the members of this set ** in order from smallest to largest. */ public Iterator iterator() { return members.iterator(); } /* Returns a new set that is the union of this set and the specified set. */ public SetOfInt union(SetOfInt s) { ArrayList resultMembers = new ArrayList(); final int M = this.members.size(); final int N = s.members.size(); int i = 0, j = 0; while (i != M && j != N) { // Add to end of resultMembers the smaller of the current elements // of this.members and s.members. int diff = this.members.get(i) - s.members.get(j); if (diff < 0) { resultMembers.add(this.members.get(i)); i = i + 1; } else if (diff > 0) { resultMembers.add(s.members.get(j)); j = j+1; } else { resultMembers.add(this.members.get(i)); i = i+1; j = j+1; } } // Now add the remaining elements of this.members to resultMembers. while (i != M) { resultMembers.add(this.members.get(i)); i = i+1; } // Now add the remaining elements of s.members to resultMembers. while (j != N) { resultMembers.add(s.members.get(j)); j = j+1; } return new SetOfInt(resultMembers); } /* Returns a new set that is the intersection of this ** set and the specified one. */ public SetOfInt intersection(SetOfInt s) { ArrayList resultMembers = new ArrayList(); final int M = this.members.size(); final int N = s.members.size(); int i = 0, j = 0; while (i != M && j != N) { // If the current elements are the same, // add it to end of resultMembers. int diff = this.members.get(i) - s.members.get(j); if (diff < 0) { i = i + 1; } else if (diff > 0) { j = j+1; } else { // elements are the same resultMembers.add(this.members.get(i)); i = i+1; j = j+1; } } return new SetOfInt(resultMembers); } /* Returns a new set that is equal to this - s, i.e., it contains ** those elements of this set that are not elements of s. */ public SetOfInt minus(SetOfInt s) { ArrayList resultMembers = new ArrayList(); final int M = this.members.size(); final int N = s.members.size(); int i = 0, j = 0; while (i != M && j != N) { int diff = this.members.get(i) - s.members.get(j); if (diff < 0) { // this.members[i] is not a member of s, so add it to the result. resultMembers.add(this.members.get(i)); i = i + 1; } else if (diff > 0) { // s.members[j] is not a member of this.members, so ignore it. j = j+1; } else { // elements are the same // this.members[i] and s.members[j] are the same, so do not // include that value in the result. i = i+1; j = j+1; } } // Now add the remaining elements of this.members to resultMembers. while (i != M) { resultMembers.add(this.members.get(i)); i = i+1; } return new SetOfInt(resultMembers); } // private methods // --------------- /* Returns k satisfying the condition that members.get(i) < item ** for all i in the range [0..k) and item <= members.get(i) for all i ** in the range [k..N) (where N = members.size()). ** pre: The values in members are in increasing order. (This is a ** class invariant.) */ private int binarySearch(int item) { // Perform a binary search in members. int low = 0, high = members.size(); while (low != high) { int mid = (low + high) / 2; if (members.get(mid) < item) { low = mid+1; } else { high = mid; } } return low; } }