0

I'm trying to create a small program to take an input 1-3 and sorts through a list of contacts using a different sorting algorithm depending on what the user selects. I've got all my code written, but I'm having an issue when I try to use my sorts. The program runs fine if I use Collections sort, but I need to use those three algorithms.

public class  {

public static void main(String[] args) {

    Contact[] contacts = {

    };


    int input;
    do{
    Scanner in = new Scanner(System.in);
    System.out.println("Sort by last name:     [0]");
    System.out.println("Sort by first name:    [1]");
    System.out.println("Sort by age:           [2]");
    System.out.println("Enter an option or 0 to end input: ");
    input = in.nextInt();

        if(input == 0)
        {
            System.out.println("Exiting...");
            System.exit(input);
        }

        else if(input == 1)
        {
            Merge.sort(contacts, new LastNameComparator());

            for(Contact contact : contacts)
            {
                System.out.println(contact);
            }
        }

        else if(input == 2)
        {
            Quick.sort(contacts, new FirstNameComparator());

            for(Contact contact : contacts)
            {   
                System.out.println(contact);
            }
        }

        else if(input == 3)
        {
            Heap.sort(contacts, new AgeComparator());

            for(Contact contact : contacts)
            {
                System.out.println(contact);
            }
        }

        else if(input > 3 || input < 0)
        {
            System.out.println("Invalid entry");
        }

    } while (input != 0);
}

}

    public class Contact implements Comparable{
    import java.util.Comparator;

    String lastName;
    String firstName;
    String homeState;
    Integer age;

    Contact(String lastName, String firstName, String homeState, Integer age)
    {
        this.lastName = lastName;
        this.firstName = firstName;
        this.homeState = homeState;
        this.age = age;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getHomeState() {
        return homeState;
    }

    public void setHomeState(String homeState) {
        this.homeState = homeState;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return String.format("%8s %8s %7s, %7d", this.lastName, this.firstName, this.homeState, this.age);
    }

    class FirstNameComparator implements Comparator<Contact> {
        public int compare(Contact a, Contact b) {
            return a.firstName.compareToIgnoreCase(b.firstName);
            }

    class LastNameComparator implements Comparator<Contact>{
         public int compare(Contact a, Contact b) {
            return a.lastName.compareToIgnoreCase(b.lastName);
            }

    class AgeComparator implements Comparator<Contact> {
         public int compare(Contact a, Contact b) {
            return a.age < b.age ? -1 : a.age == b.age ? 0 : 1;
            }

        }
    }
}

}

Any tips are greatly appreciated. Thank you!

Polyphase29
  • 475
  • 1
  • 4
  • 17

2 Answers2

0

@Mark, here are the changes that I have made.

  1. Its some ambiguous to use Comparator and Comparable, you can read this post and see the differences: What is the difference between compare() and compareTo()?

  2. Your indexes were wrong, like 0 to 'Sort by last name' and 'exit'

  3. The import is always before the class statement

  4. There were some brackets missing

4.5 There were one main method in Heap and the other options in Assignment1 that I removed just to compile

  1. I would advice you to use Generics to make this class, you can read more here: https://docs.oracle.com/javase/tutorial/java/generics/. In your Head.sort method, you definied it to receive a Comparable and you were passing a Comparable and a Comparator, like I said, its ambiguous. Its better to you pass a generic array (Like anything-> String[], int[], yourOwnClass[]) and provide a second argument: the Comparator! So, lets go back, changed to use generics and provide your Comparator! Now you are calling the method sort and saying to it what is the parameter to compare (Comparator). You can see the final result here:

    import java.util.Scanner; public class Assignment1 {

    public static void main(String[] args) {
    
    Contact[] contacts = {
            new Contact("Collins", "Kelly", "Illinois", 26),
            new Contact("Smith", "Brandon", "Michigan", 32),
            new Contact("Jones", "Mark", "California", 29),
            new Contact("McDowell", "Ryan", "Texas", 30),
            new Contact("Thompson", "April", "New York", 35)
    };
    
    
    int input;
    do {
        Scanner in = new Scanner(System.in);
        System.out.println("Sort by last name:     [1]");
        System.out.println("Sort by first name:    [2]");
        System.out.println("Sort by age:           [3]");
        System.out.println("Enter an option or 0 to end input: ");
        input = in.nextInt();
    
        if (input == 0) {
            System.out.println("Exiting...");
            System.exit(input);
        } else if (input == 3) {
            Heap.sort(contacts, new Contact.AgeComparator());
    
    
            for (Contact contact : contacts) {
                System.out.println(contact);
            }
        } else if (input > 3 || input < 0) {
            System.out.println("Invalid entry");
        }
    
    } while (input != 0);
    

    } }

Contact class:

import java.util.Comparator;

public class Contact {

String lastName;
String firstName;
String homeState;
Integer age;

Contact(String lastName, String firstName, String homeState, Integer age) {
    this.lastName = lastName;
    this.firstName = firstName;
    this.homeState = homeState;
    this.age = age;
}

public String getLastName() {
    return lastName;
}

public void setLastName(String lastName) {
    this.lastName = lastName;
}

public String getFirstName() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

public String getHomeState() {
    return homeState;
}

public void setHomeState(String homeState) {
    this.homeState = homeState;
}

public Integer getAge() {
    return age;
}

public void setAge(Integer age) {
    this.age = age;
}

@Override
public String toString() {
    return String.format("%8s %8s %7s, %7d", this.lastName, this.firstName, this.homeState, this.age);
}

static class FirstNameComparator implements Comparator<Contact> {
    public int compare(Contact a, Contact b) {
        return a.firstName.compareToIgnoreCase(b.firstName);
    }
}

static class LastNameComparator implements Comparator<Contact> {
    public int compare(Contact a, Contact b) {
        return a.lastName.compareToIgnoreCase(b.lastName);
    }
}

static  class AgeComparator implements Comparator<Contact> {
    public int compare(Contact a, Contact b) {
        return a.age < b.age ? -1 : a.age == b.age ? 0 : 1;
    }

}
}

Heap class

import java.util.Comparator;

public class Heap {

// This class should not be instantiated.
private Heap() { }

/**
 * Rearranges the array in ascending order, using the natural order.
 * @param pq the array to be sorted
 */
public static <T> void sort(T[] pq, Comparator<T> comparator) {
    int n = pq.length;
    for (int k = n/2; k >= 1; k--)
        sink(pq, k, n, comparator);
    while (n > 1) {
        exch(pq, 1, n--);
        sink(pq, 1, n, comparator);
    }
}

private static <T> void sink(T[] pq, int k, int n, Comparator<T> comparator) {
    while (2*k <= n) {
        int j = 2*k;
        if (j < n && less(pq, j, j+1, comparator)) j++;
        if (!less(pq, k, j, comparator)) break;
        exch(pq, k, j);
        k = j;
    }
}


private static <T> boolean less(T[] pq, int i, int j, Comparator<T> comparator) {
    return comparator.compare(pq[i-1],pq[j-1]) < 0;
}

private static void exch(Object[] pq, int i, int j) {
    Object swap = pq[i-1];
    pq[i-1] = pq[j-1];
    pq[j-1] = swap;
}

}

Merge

    import java.util.Comparator;

public class Merge {

    // This class should not be instantiated.
    private Merge() {
    }

    // stably merge a[lo .. mid] with a[mid+1 ..hi] using aux[lo .. hi]
    private static <T> void merge(T[] a, T[] aux, int lo, int mid, int hi, Comparator<T> comparator) {
        // precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays
        assert isSorted(a, lo, mid, comparator);
        assert isSorted(a, mid + 1, hi, comparator);

        // copy to aux[]
        for (int k = lo; k <= hi; k++) {
            aux[k] = a[k];
        }

        // merge back to a[]
        int i = lo, j = mid + 1;
        for (int k = lo; k <= hi; k++) {
            if (i > mid) a[k] = aux[j++];
            else if (j > hi) a[k] = aux[i++];
            else if (less(aux[j], aux[i], comparator)) a[k] = aux[j++];
            else a[k] = aux[i++];
        }

        // postcondition: a[lo .. hi] is sorted
        assert isSorted(a, lo, hi, comparator);
    }

    // mergesort a[lo..hi] using auxiliary array aux[lo..hi]
    private static <T> void sort(T[] a, T[] aux, int lo, int hi, Comparator<T> comparator) {
        if (hi <= lo) return;
        int mid = lo + (hi - lo) / 2;
        sort(a, aux, lo, mid, comparator);
        sort(a, aux, mid + 1, hi, comparator);
        merge(a, aux, lo, mid, hi, comparator);
    }

    /**
     * Rearranges the array in ascending order, using the natural order.
     *
     * @param a the array to be sorted
     */
    public static <T> void sort(T[] a, Comparator<T> comparator) {
        T[] aux = (T[])new Object[a.length];
        sort(a, aux, 0, a.length - 1, comparator);
        assert isSorted(a, comparator);
    }

    // is v < w ?
    private static <T> boolean less(T v, T w, Comparator<T> comparator) {
        return comparator.compare(v,w) < 0;
    }


    private static <T> boolean isSorted(T[] a, Comparator<T> comparator) {
        return isSorted(a, 0, a.length - 1, comparator);
    }

    private static <T> boolean isSorted(T[] a, int lo, int hi, Comparator<T> comparator) {
        for (int i = lo + 1; i <= hi; i++)
            if (less(a[i], a[i - 1], comparator)) return false;
        return true;
    }
}

Quick

    import java.util.Comparator;

public class Quick {
    // This class should not be instantiated.
    private Quick() {
    }

    /**
     * Rearranges the array in ascending order, using the natural order.
     *
     * @param a the array to be sorted
     */
    public static <T> void sort(T[] a, Comparator<T> comparator) {
        sort(a, 0, a.length - 1, comparator);
        assert isSorted(a, comparator);
    }

    // quicksort the subarray from a[lo] to a[hi]
    private static <T> void sort(T[] a, int lo, int hi, Comparator<T> comparator) {
        if (hi <= lo) return;
        int j = partition(a, lo, hi, comparator);
        sort(a, lo, j - 1, comparator);
        sort(a, j + 1, hi, comparator);
        assert isSorted(a, lo, hi, comparator);
    }

    // partition the subarray a[lo..hi] so that a[lo..j-1] <= a[j] <= a[j+1..hi]
// and return the index j.
    private static <T> int partition(T[] a, int lo, int hi, Comparator<T> comparator) {
        int i = lo;
        int j = hi + 1;
        T v = a[lo];
        while (true) {

            // find item on lo to swap
            while (less(a[++i], v, comparator))
                if (i == hi) break;

            // find item on hi to swap
            while (less(v, a[--j], comparator))
                if (j == lo) break;      // redundant since a[lo] acts as sentinel

            // check if pointers cross
            if (i >= j) break;

            exch(a, i, j);
        }

        // put partitioning item v at a[j]
        exch(a, lo, j);

        // now, a[lo .. j-1] <= a[j] <= a[j+1 .. hi]
        return j;
    }

    /**
     * Rearranges the array so that {@code a[k]} contains the kth smallest key;
     * {@code a[0]} through {@code a[k-1]} are less than (or equal to) {@code a[k]}; and
     * {@code a[k+1]} through {@code a[n-1]} are greater than (or equal to) {@code a[k]}.
     *
     * @param a the array
     * @param k the rank of the key
     * @return the key of rank {@code k}
     */
    public static <T> T select(T[] a, int k, Comparator<T> comparator) {
        if (k < 0 || k >= a.length) {
            throw new IndexOutOfBoundsException("Selected element out of bounds");
        }
        int lo = 0, hi = a.length - 1;
        while (hi > lo) {
            int i = partition(a, lo, hi, comparator);
            if (i > k) hi = i - 1;
            else if (i < k) lo = i + 1;
            else return a[i];
        }
        return a[lo];
    }


    // is v < w ?
    private static <T> boolean less(T v, T w, Comparator<T> comparator) {
        return comparator.compare(v, w) < 0;
    }

    // exchange a[i] and a[j]
    private static  void exch(Object[] a, int i, int j) {
        Object swap = a[i];
        a[i] = a[j];
        a[j] = swap;
    }


    private static <T>  boolean isSorted(T[] a, Comparator<T> comparator) {
        return isSorted(a, 0, a.length - 1, comparator);
    }

    private static <T> boolean isSorted(T[] a, int lo, int hi, Comparator<T> comparator) {
        for (int i = lo + 1; i <= hi; i++)
            if (less(a[i], a[i - 1], comparator)) return false;
        return true;
    }
}
Community
  • 1
  • 1
Bruno
  • 2,889
  • 1
  • 18
  • 25
  • Thanks for your thorough response! However, it still isn't working for me! I'm not sure what it is. For example, I have an error pop up on the side of my "Heap.sort" line that states: "The method sort(Comparable[]) in the type Heap is not applicable for the arguments (Contact[], Contact.AgeComparator". Obviously it's having some sort of issue with the argument I'm trying to put into the sort. How can I fix this? – Polyphase29 Nov 01 '16 at 02:25
  • Did you changed the methods signatures with the ones that I provided to you? Did you noticed that I have changed they? – Bruno Nov 01 '16 at 02:27
  • Ahh! That does work! Okay, so if I want to update my Merge and Quick sorts accordingly, what line am I looking to change? – Polyphase29 Nov 01 '16 at 02:39
  • Pay attention to the methods signatures! I have add before the return type and chaged the parameter from Comparable to T. Plust that, we are now passing the comparator propertly throung the methods and change the call that was pq[].compareTo(pq[]) to return comparator.compare! – Bruno Nov 01 '16 at 02:44
  • Let me add my Merge and Quick sorts to my initial question, it's kind of going a bit over my head. – Polyphase29 Nov 01 '16 at 02:47
  • Okay, I added them. Thanks so much for the help - I really appreciate it. – Polyphase29 Nov 01 '16 at 02:50
  • @Mark if my answer really helped you, dont forget to marke it as the "best" answer, its important :) – Bruno Nov 01 '16 at 02:52
  • Done - please let me know about the other algorithms I just put up if possible. Thanks! – Polyphase29 Nov 01 '16 at 02:58
0

See you are passing two argument in

 Heap.sort(contacts, new AgeComparator());

Now if you see sort method of Heap class

public static void sort(Comparable[] pq) {
int n = pq.length;
for (int k = n/2; k >= 1; k--)
    sink(pq, k, n);
while (n > 1) {
    exch(pq, 1, n--);
    sink(pq, 1, n);
}

It accepts only one argument, so you need to modify it for two arguments. Refer this in case you need: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Collections.java#Collections.sort%28java.util.List%2Cjava.util.Comparator%29

Bhagwati Malav
  • 3,349
  • 2
  • 20
  • 33