实现堆使用java对象排序

时间:2013-11-07 15:03:28

标签: java oop data-structures arraylist heapsort

我被赋予了使用java实现堆排序的任务。排序将按年薪计算,但对象员工将接受名称字符串和工资int。我已经成功使用基本相同类的bubblesort但我在堆排序方面遇到了一些麻烦。这是我的代码:

import java.util.ArrayList;
 import java.util.Scanner;

public class Company {



//create a default heap using array list
private ArrayList<Employee> list = new ArrayList<Employee>();

/* Add a new object into the binary heap */
//building a heap

public void addEmployee(Employee employee) {
    list.add(employee); //append to the heap
}

public Employee remove() {
int count = 0;
if (list.isEmpty())
    return null;

Employee removedObject = list.get(0);
list.set(0, list.get(list.size() - 1));
list.remove(list.size() - 1);

int currentIndex = 0;
while (currentIndex < list.size()) {
    int leftChildIndex = 2 * currentIndex + 1;
    int rightChildIndex = 2 * currentIndex + 2;

    // find the maximum between the two children
    if (leftChildIndex >= list.size())
        break; // the tree is a heap

    int maxIndex = leftChildIndex;
    if (rightChildIndex < list.size()) {
        if (list.get(maxIndex).compareTo(list.get(rightChildIndex)) < 0) {
            maxIndex = rightChildIndex;
            count++;
        }
    }
    // swap if the current node is less than the maximum
    if (list.get(currentIndex).compareTo(list.get(maxIndex)) < 0) {
        Employee temp = list.get(maxIndex);
        list.set(maxIndex, list.get(currentIndex));
        list.set(currentIndex, temp);
        currentIndex = maxIndex;
        count++;

    }
    else
        break;
}
// This is what I changed.
//list.add(0, removedObject);
//count++;
System.out.println(count);
return removedObject;

}


        /*
         * Method to print all elements in the ArrayList
         */

        public void listEmployees(){
            for (Employee employee : list)
                System.out.println(employee.toString());
            System.out.println();
        }

        public void listEmployeesSorted() {
            ArrayList<Employee> copy = new ArrayList<Employee>(list);
            StringBuilder builder = new StringBuilder();
            while (list.size()>0) {
                Employee e = this.remove();
                builder.append(e.toString()+"\n");
            }
            this.list = copy;
            System.out.println(builder.toString());
        }

        public static void main(String[] args) { 

            /*
             * Instantiate object and call it 'direct'
             */   
            Company direct = new Company();

            Scanner input=new Scanner(System.in);//Scanner Declaration
            String name;
            int salary;

            /*
             * Enter all the employee data
             */
            direct.addEmployee(new EmployeeImp("John Hughes",36100));
            direct.addEmployee(new EmployeeImp("Stephen Hughes",22100));
            direct.addEmployee(new EmployeeImp("Michael Smith", 0));
            direct.addEmployee(new EmployeeImp("Ludmilia Petrushevskaya", 120120));
            direct.addEmployee(new EmployeeImp("Amy Gu", 36100));
            direct.addEmployee(new EmployeeImp("Marta Villanueva Cortez", 34020));
            direct.addEmployee(new EmployeeImp("Ian Palmer-Jones", 23090));
            direct.addEmployee(new EmployeeImp("Andrew Andrews", 220100));
            direct.addEmployee(new EmployeeImp("Andy Rainsford", 67000));
            direct.addEmployee(new EmployeeImp("Bob Bobsworth", 23000));
            direct.addEmployee(new EmployeeImp("Paul Smith", 29000));
            direct.addEmployee(new EmployeeImp("James James", 23023));
            direct.addEmployee(new EmployeeImp("Henry Cooper", 33900));
            direct.addEmployee(new EmployeeImp("Ian Paisley", 33901));
            direct.addEmployee(new EmployeeImp("Alan Ball", 45000));
            direct.addEmployee(new EmployeeImp("Mick Channon", 55600));
            direct.addEmployee(new EmployeeImp("Paul Halibut", 26780));
            direct.addEmployee(new EmployeeImp("Raj Patel", 33090));
            direct.addEmployee(new EmployeeImp("Mary James", 23000));
            direct.addEmployee(new EmployeeImp("Alison Frogget", 78100));
            direct.addEmployee(new EmployeeImp("Jenny Eclair", 40000));
            direct.addEmployee(new EmployeeImp("Sasha Lane", 21000));
            direct.addEmployee(new EmployeeImp("Sarah Milligan", 100300));
            direct.addEmployee(new EmployeeImp("Zico", 120000));
            direct.addEmployee(new EmployeeImp("Pippa Forester", 90000));
            direct.addEmployee(new EmployeeImp("Angela Landsdowne", 8000));
            direct.addEmployee(new EmployeeImp("Emily Taxem", -1000));
            direct.addEmployee(new EmployeeImp("Jill Beans", 654000));
            direct.addEmployee(new EmployeeImp("Alan Salt", 33333));
            direct.addEmployee(new EmployeeImp("Imran Khan", 87000));
            direct.addEmployee(new EmployeeImp("Matt Demon", 66666));
            direct.addEmployee(new EmployeeImp("Douglas Adams", 42000));

            System.out.println("\tName\t\t Salary");
            direct.listEmployees();//print out all elements in ArrayList before sorting
            System.out.println("\tName\t\t Salary");
            System.out.println("__________________________________________________");              
            direct.listEmployeesSorted();//print out all elements in ArrayList after sorting

            /*
             * Use scanner to get user input (name,salary) to be entered into
             * the existing sorted list
             */

            System.out.print("Please enter a new employee's name: ");
            name=input.nextLine();
            System.out.print("Please enter the employee's associated salary: ");
            salary=input.nextInt(); 

            direct.addEmployee(new EmployeeImp(name,salary));
            direct.listEmployeesSorted();
        }//end main


}//end class Company

对于少量数据,它排序很好,但是当我开始添加负数或0或甚至有时只是正常的正值时,整个排序变得疯狂。我想知道是否有人可以帮我解决这个问题。我知道一个事实是我的堆排序方法的实现给出了问题,其他一切都应该没问题...大声笑......请协助

这是员工类:

public abstract class Employee implements Comparable<Employee>{
private String name;
private int salary;  

/*
 * Two-Arguement Constructor
 */

 Employee(String name, int salary){
  this.name = name;
   this.salary = salary;
 }//end method
    public int getSalary(){
    return salary;
   }//end method

  /*
     * Return the employee's name
      */

 public String getName(){
  return name;
 }//end method


/*
 * Return the compareTo
 */

public int compareTo(Employee x){
if (this.salary < x.salary)
    return -1;
else if (this.salary > x.salary)
    return 1;
else 
    return 0;
}//end method
public String toString(){        
StringBuffer buffer = new StringBuffer();        
buffer.append("\t");
buffer.append(getName());
buffer.append("\t  ");
buffer.append(getSalary());
buffer.append("\t  ");
return buffer.toString();
}
}

这是实现员工的子类:

class EmployeeImp extends Employee{

EmployeeImp(String name, int salary) {
    super(name, salary);
}
}

enter image description here enter image description here

1 个答案:

答案 0 :(得分:0)

我相信这是你的问题;为什么你在删除结束时这样做?

list.add(0, removedObject);
count++;

是否应将其删除?

//list.add(0, removedObject);
//count++;

我在代码的本地副本上进行了上述更改(将Employee更改为不抽象),它似乎工作正常。我使用下面的validatino代码来检查使用随机数据。

public boolean validate() {
    Employee p = this.remove();
    while (list.size()>0) {
        Employee e = this.remove();
        if (e.compareTo(p)>0) return false;
        p = e;
    }
    return true;
}

测试代码。

    boolean result = false;
    for (int x=0; x<100; x++) {
        int size = 100000;
        for (int i=0; i<size; i++) {
            int r = RANDOM.nextInt();
            company.addEmployee(new Employee(String.valueOf(r),r));
        }
        result = company.validate();
        if (result==false) break;
    }
    System.out.println(result);

以下是完整删除方法:

public Employee remove() {
    int count = 0;
    if (list.isEmpty())
        return null;

    Employee removedObject = list.get(0);
    list.set(0, list.get(list.size() - 1));
    list.remove(list.size() - 1);

    int currentIndex = 0;
    while (currentIndex < list.size()) {
        int leftChildIndex = 2 * currentIndex + 1;
        int rightChildIndex = 2 * currentIndex + 2;

        // find the maximum between the two children
        if (leftChildIndex >= list.size())
            break; // the tree is a heap

        int maxIndex = leftChildIndex;
        if (rightChildIndex < list.size()) {
            if (list.get(maxIndex).compareTo(list.get(rightChildIndex)) < 0) {
                maxIndex = rightChildIndex;
                count++;
            }
        }
        // swap if the current node is less than the maximum
        if (list.get(currentIndex).compareTo(list.get(maxIndex)) < 0) {
            Employee temp = list.get(maxIndex);
            list.set(maxIndex, list.get(currentIndex));
            list.set(currentIndex, temp);
            currentIndex = maxIndex;
            count++;

        }
        else
            break;
    }
    // This is what I changed.
    //list.add(0, removedObject);
    //count++;
    System.out.println(count);
    return removedObject;

}

示例数据...请记住,(最大)堆的唯一保证是顶部元素将是堆中的最大值,并且每个父级将大于或等于它的子级。

Input order:                   5, 12, 12, 17, 8, 7, 4, 1, 5, 19, 
Companies internal list order: 19=19, 17=17, 12=12, 5=5, 12=12, 7=7, 4=4, 1=1, 5=5, 8=8, 
Heap sorted order:             19=19, 17=17, 12=12, 12=12, 8=8, 7=7, 5=5, 5=5, 4=4, 1=1, 

公司的非破坏性打印方法(它实际上是破坏性的,但在完成打印后返回初始状态):

public String toString() {
    ArrayList<Employee> copy = new ArrayList<Employee>(list);
    StringBuilder builder = new StringBuilder();
    while (list.size()>0) {
        Employee e = this.remove();
        builder.append(e.toString()+"\n");
    }
    this.list = copy;
    return builder.toString();
}