热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

之前Arrays类中存在sort()方法,此方法可以直接对对象数组进行排序。1.Comparable接口可以直接使用java.util.Arrays类进行数组的排序操作,但对象所在的类必须

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

 1.Comparable接口

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

Comparable 接口定义如下:

public interface Comparable{

public int compareTo(T o);

}

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

1:表示大于 

-1:表示小于

0:表示相等

要求:

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

class Student implements Comparable {// 指定类型为Student
private String name ;
private int age ;
private float score ;
public Student(String name,int age,float score){
this.name = name ;
this.age = age ;
this.score = score ;
}
public String toString(){
return name + "\t\t" + this.age + "\t\t" + this.score ;
}
public int compareTo(Student stu){// 覆写compareTo()方法,实现排序规则的应用
if(this.score>stu.score){
return -1 ;
}else if(this.scorereturn 1 ;
}else{
if(this.age>stu.age){
return 1 ;
}else if(this.agereturn -1 ;
}else{
return 0 ;
}
}
}
};
public class ComparableDemo01{
public static void main(String args[]){
Student stu[] = {new Student("张三",20,90.0f),
new Student("李四",22,90.0f),new Student("王五",20,99.0f),
new Student("赵六",20,70.0f),new Student("孙七",22,100.0f)} ;
java.util.Arrays.sort(stu) ;// 进行排序操作
for(int i=0;iSystem.out.println(stu[i]) ;
}
}
};
2.分析比较器的排序原理

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

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

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

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

public class ComparableDemo02{
public static void main(String args[]){
Comparable com = null ;// 声明一个Comparable接口对象
com = 30 ;// 通过Integer为Comparable实例化
System.out.println("内容为:" + com) ;// 调用的是toString()方法
}
};
了解了此特性之后,下面就可以动物完成一个二叉树算法。

class BinaryTree{
class Node{// 声明一个节点类
private Comparable data ;// 保存具体的内容
private Node left ;// 保存左子树
private Node right ;// 保存右子树
public Node(Comparable data){
this.data = data ;
}
public void addNode(Node newNode){
// 确定是放在左子树还是右子树
if(newNode.data.compareTo(this.data)<0){// 内容小,放在左子树
if(this.left==null){
this.left = newNode ;// 直接将新的节点设置成左子树
}else{
this.left.addNode(newNode) ;// 继续向下判断
}
}
if(newNode.data.compareTo(this.data)>=0){// 放在右子树
if(this.right==null){
this.right = newNode ;// 没有右子树则将此节点设置成右子树
}else{
this.right.addNode(newNode) ;// 继续向下判断
}
}
}
public void printNode(){// 输出的时候采用中序遍历
if(this.left!=null){
this.left.printNode() ;// 输出左子树
}
System.out.print(this.data + "\t") ;
if(this.right!=null){
this.right.printNode() ;
}
}
};
private Node root ;// 根元素
public void add(Comparable data){// 加入元素
Node newNode = new Node(data) ;// 定义新的节点
if(root==null){// 没有根节点
root = newNode ;// 第一个元素作为根节点
}else{
root.addNode(newNode) ; // 确定是放在左子树还是放在右子树
}
}
public void print(){
this.root.printNode() ;// 通过根节点输出
}
};
public class ComparableDemo03{
public static void main(String args[]){
BinaryTree bt = new BinaryTree() ;
bt.add(8) ;
bt.add(3) ;
bt.add(3) ;
bt.add(10) ;
bt.add(9) ;
bt.add(1) ;
bt.add(5) ;
bt.add(5) ;
System.out.println("排序之后的结果:") ;
bt.print() ;
}
};
另一种比较器:Comparator

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

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

public interface Comparator{

public int compare(T o1, T o2);

boolean equals(Object obj);

}

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

import java.util.* ;
class Student{// 指定类型为Student
private String name ;
private int age ;
public Student(String name,int age){
this.name = name ;
this.age = age ;
}
public boolean equals(Object obj){// 覆写equals方法
if(this==obj){
return true ;
}
if(!(obj instanceof Student)){
return false ;
}
Student stu = (Student) obj ;
if(stu.name.equals(this.name)&&stu.age==this.age){
return true ;
}else{
return false ;
}
}
public void setName(String name){
this.name = name ;
}
public void setAge(int age){
this.age = age ;
}
public String getName(){
return this.name ;
}
public int getAge(){
return this.age ;
}
public String toString(){
return name + "\t\t" + this.age ;
}
};

class StudentComparator implements Comparator{// 实现比较器
// 因为Object类中本身已经有了equals()方法
public int compare(Student s1,Student s2){
if(s1.equals(s2)){
return 0 ;
}else if(s1.getAge()return 1 ;
}else{
return -1 ;
}
}
};

public class ComparatorDemo{
public static void main(String args[]){
Student stu[] = {new Student("张三",20),
new Student("李四",22),new Student("王五",20),
new Student("赵六",20),new Student("孙七",22)} ;
java.util.Arrays.sort(stu,new StudentComparator()) ;// 进行排序操作
for(int i=0;iSystem.out.println(stu[i]) ;
}
}
};

总结:

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

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







推荐阅读
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
author-avatar
黑铁1988
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有