首页 > 代码库 > 比较器(Comparable、Comparator)类及 二叉树的排序算法

比较器(Comparable、Comparator)类及 二叉树的排序算法

之前Arrays 类中存在sort() 方法, 此方法可以直接对 对象数组进行排序。

1.Comparable接口

可以直接使用java.util.Arrays 类进行数组的排序操作,但对象所在的类必须实现Comparable 接口,用于指定排序接口。

Comparable 接口定义如下:

public interface Comparable<T>{

public int compareTo(T o);

}

此方法返回一个int 类型的数据,但是此int 的值只能是以下三种:

  1:表示大于

  1:表示小于

  0:表示相等

要求:

定义一个学生类,里面有姓名、年龄、成绩三个属性,要求按成绩由高到低排序,如果成绩相等,则按照年龄由低到高排序。

 1 class Student implements Comparable<Student> {    // 指定类型为Student 2     private String name ; 3     private int age ; 4     private float score ; 5     public Student(String name,int age,float score){ 6         this.name = name ; 7         this.age = age ; 8         this.score = score ; 9     }10     public String toString(){11         return name + "\t\t" + this.age + "\t\t" + this.score ;12     }13     public int compareTo(Student stu){    // 覆写compareTo()方法,实现排序规则的应用14         if(this.score>stu.score){15             return -1 ;16         }else if(this.score<stu.score){17             return 1 ;18         }else{19             if(this.age>stu.age){20                 return 1 ;21             }else if(this.age<stu.age){22                 return -1 ;23             }else{24                 return 0 ;25             }26         }    27     }28 }29 public class ComparableDemo01{30     public static void main(String args[]){31         Student stu[] = {new Student("张三",20,90.0f),32             new Student("李四",22,90.0f),new Student("王五",20,99.0f),33             new Student("赵六",20,70.0f),new Student("孙七",22,100.0f)} ;34         java.util.Arrays.sort(stu) ;    // 进行排序操作35         for(int i=0;i<stu.length;i++){    // 循环输出数组中的内容36             System.out.println(stu[i]) ;37         }38     }39 }

2.分析比较器的排序原理

实际上比较器的操作,就是经常听到的二叉树的排序算法。通过二叉树进行排序,之后利用中序遍历的方法把内容依次读取出来。

排序的基本原理,使用第一个元素作为根节点,之后如果后面的内容比根节点要大,则放在左子树,如果内容比根节点的内容要大,则放在右子树。

下面就自己手式实现一个二叉树的比较算法。

为了操作方便,此处使用Integer 类完成。

1 public class ComparableDemo02{2     public static void main(String args[]){3         Comparable com = null ;            // 声明一个Comparable接口对象4         com = 30 ;                        // 通过Integer为Comparable实例化5         System.out.println("内容为:" + com) ;    // 调用的是toString()方法6     }7 };

了解了此特性之后,下面就可以完成一个二叉树算法。

 1 class BinaryTree{ 2     class Node{            // 声明一个节点类 3         private Comparable data ;    // 保存具体的内容 4         private Node left ;            // 保存左子树 5         private Node right ;        // 保存右子树 6         public Node(Comparable data){ 7             this.data =http://www.mamicode.com/ data ; 8         } 9         public void addNode(Node newNode){10             // 确定是放在左子树还是右子树11             if(newNode.data.compareTo(this.data)<0){    // 内容小,放在左子树12                 if(this.left==null){13                     this.left = newNode ;    // 直接将新的节点设置成左子树14                 }else{15                     this.left.addNode(newNode) ;    // 继续向下判断16                 }17             }18             if(newNode.data.compareTo(this.data)>=0){    // 放在右子树19                 if(this.right==null){20                     this.right = newNode ;    // 没有右子树则将此节点设置成右子树21                 }else{22                     this.right.addNode(newNode) ;    // 继续向下判断23                 }24             }25         }26         public void printNode(){    // 输出的时候采用中序遍历27             if(this.left!=null){28                 this.left.printNode() ;    // 输出左子树29             }30             System.out.print(this.data + "\t") ;31             if(this.right!=null){32                 this.right.printNode() ;33             }34         }35     };36     private Node root ;        // 根元素37     public void add(Comparable data){    // 加入元素38         Node newNode = new Node(data) ;    // 定义新的节点39         if(root==null){    // 没有根节点40             root = newNode ;    // 第一个元素作为根节点41         }else{42             root.addNode(newNode) ; // 确定是放在左子树还是放在右子树43         }44     }45     public void print(){46         this.root.printNode() ;    // 通过根节点输出47     }48 };49 public class ComparableDemo03{50     public static void main(String args[]){51         BinaryTree bt = new BinaryTree() ;52         bt.add(8) ;53         bt.add(3) ;54         bt.add(3) ;55         bt.add(10) ;56         bt.add(9) ;57         bt.add(1) ;58         bt.add(5) ;59         bt.add(5) ;60         System.out.println("排序之后的结果:") ;61         bt.print() ;62     }63 };

另一种比较器:Comparator
如果一个类已经开发完成,但是在此类建立的初期并没有实现Comparable接口,此时肯定是无法进行对象排序操作的所以为了解决这样的问题,java又定义了另一个比较器的操作接口——Comparator。

此接口定义在java.util 包中,接口定义如下:

public interface Comparator<T>{

public int compare(T o1, T o2);

boolean equals(Object obj);

}

下面定义一个自己的类,此类没有实现Comparable接口。

 1 import java.util.* ; 2 class Student{    // 指定类型为Student 3     private String name ; 4     private int age ; 5     public Student(String name,int age){ 6         this.name = name ; 7         this.age = age ; 8     } 9     public boolean equals(Object obj){    // 覆写equals方法10         if(this==obj){11             return true ;12         }13         if(!(obj instanceof Student)){14             return false ;15         }16         Student stu = (Student) obj ;17         if(stu.name.equals(this.name)&&stu.age==this.age){18             return true ;19         }else{20             return false ;21         }22     }23     public void setName(String name){24         this.name = name ;25     }26     public void setAge(int age){27         this.age = age ;28     }29     public String getName(){30         return this.name ;31     }32     public int getAge(){33         return this.age ;34     }35     public String toString(){36         return name + "\t\t" + this.age  ;37     }38 };39 40 class StudentComparator implements Comparator<Student>{    // 实现比较器41     // 因为Object类中本身已经有了equals()方法42     public int compare(Student s1,Student s2){43         if(s1.equals(s2)){44             return 0 ;45         }else if(s1.getAge()<s2.getAge()){    // 按年龄比较46             return 1 ;47         }else{48             return -1 ;49         }50     }51 };52 53 public class ComparatorDemo{54     public static void main(String args[]){55         Student stu[] = {new Student("张三",20),56             new Student("李四",22),new Student("王五",20),57             new Student("赵六",20),new Student("孙七",22)} ;58         java.util.Arrays.sort(stu,new StudentComparator()) ;    // 进行排序操作59         for(int i=0;i<stu.length;i++){    // 循环输出数组中的内容60             System.out.println(stu[i]) ;61         }62     }63 };

总结:
在使用中尽可以还是作用Comparable 在需要排序的类上实现好此接口,而Comparator 需要单独建立一个排序的类,这样如果有很多的话,则排序的规则类也就会非常多,操作起来比较麻烦。

掌握一点:只要是对象排序,则在javak 永远是以Comparable 接口为准的。