• 注册
  • 赞助本站

    • 微信
    • 支付宝
    • Q Q

    感谢一直支持本站的所有人!

    • 查看作者
    • 《算法第四版》课后练习题1.2.13答案

      习题1.2.13

      用我们对 Date 的实现(请见表1.1.12)作为模板,开发 Transaction 的实现。

      要点分析

      1.  Date实现

       Date 的API,请见表1.1.12,课本56页,这里也给出官方网站Date类具体实现[1] 

      public class Date implements Comparable<Date> {
          private static final int[] DAYS = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
      
          private final int month;   // month (between 1 and 12)
          private final int day;     // day   (between 1 and DAYS[month]
          private final int year;    // year
      
          /**
           * Initializes a new date from the month, day, and year.
           *
           * @param month the month (between 1 and 12)
           * @param day   the day (between 1 and 28-31, depending on the month)
           * @param year  the year
           * @throws IllegalArgumentException if this date is invalid
           */
          public Date(int month, int day, int year) {
              if (!isValid(month, day, year)) throw new IllegalArgumentException("Invalid date");
              this.month = month;
              this.day = day;
              this.year = year;
          }
      
          /**
           * Initializes new date specified as a string in form MM/DD/YYYY.
           *
           * @param date the string representation of this date
           * @throws IllegalArgumentException if this date is invalid
           */
          public Date(String date) {
              String[] fields = date.split("/");
              if (fields.length != 3) {
                  throw new IllegalArgumentException("Invalid date");
              }
              month = Integer.parseInt(fields[0]);
              day = Integer.parseInt(fields[1]);
              year = Integer.parseInt(fields[2]);
              if (!isValid(month, day, year)) throw new IllegalArgumentException("Invalid date");
          }
      
          /**
           * Return the month.
           *
           * @return the month (an integer between 1 and 12)
           */
          public int month() {
              return month;
          }
      
          /**
           * Returns the day.
           *
           * @return the day (an integer between 1 and 31)
           */
          public int day() {
              return day;
          }
      
          /**
           * Returns the year.
           *
           * @return the year
           */
          public int year() {
              return year;
          }
      
      
          // is the given date valid?
          private static boolean isValid(int m, int d, int y) {
              if (m < 1 || m > 12) return false;
              if (d < 1 || d > DAYS[m]) return false;
              if (m == 2 && d == 29 && !isLeapYear(y)) return false;
              return true;
          }
      
          // is y a leap year?
          private static boolean isLeapYear(int y) {
              if (y % 400 == 0) return true;
              if (y % 100 == 0) return false;
              return y % 4 == 0;
          }
      
          /**
           * Returns the next date in the calendar.
           *
           * @return a date that represents the next day after this day
           */
          public Date next() {
              if (isValid(month, day + 1, year)) return new Date(month, day + 1, year);
              else if (isValid(month + 1, 1, year)) return new Date(month + 1, 1, year);
              else return new Date(1, 1, year + 1);
          }
      
          /**
           * Compares two dates chronologically.
           *
           * @param that the other date
           * @return {@code true} if this date is after that date; {@code false} otherwise
           */
          public boolean isAfter(Date that) {
              return compareTo(that) > 0;
          }
      
          /**
           * Compares two dates chronologically.
           *
           * @param that the other date
           * @return {@code true} if this date is before that date; {@code false} otherwise
           */
          public boolean isBefore(Date that) {
              return compareTo(that) < 0;
          }
      
          /**
           * Compares two dates chronologically.
           *
           * @return the value {@code 0} if the argument date is equal to this date;
           * a negative integer if this date is chronologically less than
           * the argument date; and a positive ineger if this date is chronologically
           * after the argument date
           */
          @Override
          public int compareTo(Date that) {
              if (this.year < that.year) return -1;
              if (this.year > that.year) return +1;
              if (this.month < that.month) return -1;
              if (this.month > that.month) return +1;
              if (this.day < that.day) return -1;
              if (this.day > that.day) return +1;
              return 0;
          }
      
          /**
           * Returns a string representation of this date.
           *
           * @return the string representation in the format MM/DD/YYYY
           */
          @Override
          public String toString() {
              return month + "/" + day + "/" + year;
          }
      
          /**
           * Compares this date to the specified date.
           *
           * @param other the other date
           * @return {@code true} if this date equals {@code other}; {@code false} otherwise
           */
          @Override
          public boolean equals(Object other) {
              if (other == this) return true;
              if (other == null) return false;
              if (other.getClass() != this.getClass()) return false;
              Date that = (Date) other;
              return (this.month == that.month) && (this.day == that.day) && (this.year == that.year);
          }
      
          /**
           * Returns an integer hash code for this date.
           *
           * @return an integer hash code for this date
           */
          @Override
          public int hashCode() {
              int hash = 17;
              hash = 31 * hash + month;
              hash = 31 * hash + day;
              hash = 31 * hash + year;
              return hash;
          }
      
          /**
           * Unit tests the {@code Date} data type.
           *
           * @param args the command-line arguments
           */
          public static void main(String[] args) {
              Date today = new Date(2, 25, 2004);
              StdOut.println(today);
              for (int i = 0; i < 10; i++) {
                  today = today.next();
                  StdOut.println(today);
              }
      
              StdOut.println(today.isAfter(today.next()));
              StdOut.println(today.isAfter(today));
              StdOut.println(today.next().isAfter(today));
      
      
              Date birthday = new Date(10, 16, 1971);
              StdOut.println(birthday);
              for (int i = 0; i < 10; i++) {
                  birthday = birthday.next();
                  StdOut.println(birthday);
              }
          }
      
      }

      2.  Transaction

      Transaction的API,请见课本48页,如下图:

      我们参考Date模板的实现以及Transaction的API编写即可。

      官方答案

      Below is the syntax highlighted version of Transaction.java from §1.2 Data Abstraction.
      
      
      /******************************************************************************
       *  Compilation:  javac Transaction.java
       *  Execution:    java Transaction
       *  Dependencies: StdOut.java
       *  
       *  Data type for commercial transactions.
       *
       ******************************************************************************/
      
      import java.util.Arrays;
      import java.util.Comparator;
      
      /**
       *  The {@code Transaction} class is an immutable data type to encapsulate a
       *  commercial transaction with a customer name, date, and amount.
       *  <p>
       *  For additional documentation, 
       *  see <a href="https://algs4.cs.princeton.edu/12oop">Section 1.2</a> of 
       *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne. 
       *
       *  @author Robert Sedgewick
       *  @author Kevin Wayne
       */
      public class Transaction implements Comparable<Transaction> {
          private final String  who;      // customer
          private final Date    when;     // date
          private final double  amount;   // amount
      
      
          /**
           * Initializes a new transaction from the given arguments.
           *
           * @param  who the person involved in this transaction
           * @param  when the date of this transaction
           * @param  amount the amount of this transaction
           * @throws IllegalArgumentException if {@code amount} 
           *         is {@code Double.NaN}, {@code Double.POSITIVE_INFINITY},
           *         or {@code Double.NEGATIVE_INFINITY}
           */
          public Transaction(String who, Date when, double amount) {
              if (Double.isNaN(amount) || Double.isInfinite(amount))
                  throw new IllegalArgumentException("Amount cannot be NaN or infinite");
              this.who    = who;
              this.when   = when;
              this.amount = amount;
          }
      
          /**
           * Initializes a new transaction by parsing a string of the form NAME DATE AMOUNT.
           *
           * @param  transaction the string to parse
           * @throws IllegalArgumentException if {@code amount} 
           *         is {@code Double.NaN}, {@code Double.POSITIVE_INFINITY},
           *         or {@code Double.NEGATIVE_INFINITY}
           */
          public Transaction(String transaction) {
              String[] a = transaction.split("\\s+");
              who    = a[0];
              when   = new Date(a[1]);
              amount = Double.parseDouble(a[2]);
              if (Double.isNaN(amount) || Double.isInfinite(amount))
                  throw new IllegalArgumentException("Amount cannot be NaN or infinite");
          }
      
          /**
           * Returns the name of the customer involved in this transaction.
           *
           * @return the name of the customer involved in this transaction
           */
          public String who() {
              return who;
          }
       
          /**
           * Returns the date of this transaction.
           *
           * @return the date of this transaction
           */
          public Date when() {
              return when;
          }
       
          /**
           * Returns the amount of this transaction.
           *
           * @return the amount of this transaction
           */
          public double amount() {
              return amount;
          }
      
          /**
           * Returns a string representation of this transaction.
           *
           * @return a string representation of this transaction
           */
          @Override
          public String toString() {
              return String.format("%-10s %10s %8.2f", who, when, amount);
          }
      
          /**
           * Compares two transactions by amount.
           *
           * @param  that the other transaction
           * @return { a negative integer, zero, a positive integer}, depending
           *         on whether the amount of this transaction is { less than,
           *         equal to, or greater than } the amount of that transaction
           */
          public int compareTo(Transaction that) {
              return Double.compare(this.amount, that.amount);
          }    
      
          /**
           * Compares this transaction to the specified object.
           *
           * @param  other the other transaction
           * @return true if this transaction is equal to {@code other}; false otherwise
           */
          @Override
          public boolean equals(Object other) {
              if (other == this) return true;
              if (other == null) return false;
              if (other.getClass() != this.getClass()) return false;
              Transaction that = (Transaction) other;
              return (this.amount == that.amount) && (this.who.equals(that.who))
                                                  && (this.when.equals(that.when));
          }
      
      
          /**
           * Returns a hash code for this transaction.
           *
           * @return a hash code for this transaction
           */
          public int hashCode() {
              int hash = 1;
              hash = 31*hash + who.hashCode();
              hash = 31*hash + when.hashCode();
              hash = 31*hash + ((Double) amount).hashCode();
              return hash;
              // return Objects.hash(who, when, amount);
          }
      
          /**
           * Compares two transactions by customer name.
           */
          public static class WhoOrder implements Comparator<Transaction> {
      
              @Override
              public int compare(Transaction v, Transaction w) {
                  return v.who.compareTo(w.who);
              }
          }
      
          /**
           * Compares two transactions by date.
           */
          public static class WhenOrder implements Comparator<Transaction> {
      
              @Override
              public int compare(Transaction v, Transaction w) {
                  return v.when.compareTo(w.when);
              }
          }
      
          /**
           * Compares two transactions by amount.
           */
          public static class HowMuchOrder implements Comparator<Transaction> {
      
              @Override
              public int compare(Transaction v, Transaction w) {
                  return Double.compare(v.amount, w.amount);
              }
          }
      
      
          /**
           * Unit tests the {@code Transaction} data type.
           *
           * @param args the command-line arguments
           */
          public static void main(String[] args) {
              Transaction[] a = new Transaction[4];
              a[0] = new Transaction("Turing   6/17/1990  644.08");
              a[1] = new Transaction("Tarjan   3/26/2002 4121.85");
              a[2] = new Transaction("Knuth    6/14/1999  288.34");
              a[3] = new Transaction("Dijkstra 8/22/2007 2678.40");
      
              StdOut.println("Unsorted");
              for (int i = 0; i < a.length; i++)
                  StdOut.println(a[i]);
              StdOut.println();
              
              StdOut.println("Sort by date");
              Arrays.sort(a, new Transaction.WhenOrder());
              for (int i = 0; i < a.length; i++)
                  StdOut.println(a[i]);
              StdOut.println();
      
              StdOut.println("Sort by customer");
              Arrays.sort(a, new Transaction.WhoOrder());
              for (int i = 0; i < a.length; i++)
                  StdOut.println(a[i]);
              StdOut.println();
      
              StdOut.println("Sort by amount");
              Arrays.sort(a, new Transaction.HowMuchOrder());
              for (int i = 0; i < a.length; i++)
                  StdOut.println(a[i]);
              StdOut.println();
          }
      
      }

      参考资料

      [1] Algs4:Date.java

      [2] Algs4:Transaction.java

    • 0
    • 0
    • 554
    • 单栏布局 侧栏位置: