优先级队列-----堆

目录

二叉树的存储方式

优先级队列

比较两个自定义类型是否相等,覆写object中的equals()方法

 比较两个自定义的对象大小,覆写Comparable接口

Comparator比较器

==和equals的区别

Comparable和Comparator的区别


堆逻辑上首先是一棵完全二叉树

大根堆/大堆:堆中根节点值 >= 子树的节点值,叫做大堆/大根堆/最大堆

小根堆/小堆:堆中根节点值 <= 子树的节点值,叫做小堆/大根堆/最大堆

注意

在最大堆中,当前的根节点是最大的,在任意子树中也满足

节点的大小关系和所处的层次无关

二叉树的存储方式

使用数组保存二叉树结构,将二叉树用层序遍历方式放入数组中

使用顺序表存储完全二叉树时,节点的索引和节点的关系如下:

根节点从0开始编号,已知父节点为k左子树索引为2k+1右子树索引为2k+2

已知子节点为k父节点就是(k-1)/ 2

优先级队列

优先级队列处理的元素是动态变化的,有进有出

JDK中的优先级队列默认是最小堆的实现,队首就是当前队列的最小值

  • 比较两个自定义类型是否相等,覆写object中的equals()方法

class Student {
    String name;
    int age;

    public boolean equals(Object o){
        if (o == null){
            return false;
        }
        if (this == o){
            return true;
        }
        //判断传入的o是否是一个类的实例
        if (!(o instanceof Student)){
            return false;
        }
        Student student = (Student) o;
        return this.age == student.age && this.name.equals(student.name);
    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  •  比较两个自定义的对象大小,覆写Comparable接口

java.lang.Comparable返回一个int值

 返回值<0时,当前对象<传入对象

 返回值=0时,当前对象=传入对象 

 返回值>0时,当前对象>传入对象 

class Student implements Comparable<Student> {
    String name;
    int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }


    @Override
    public int compareTo(Student o) {
        return this.age - o.age;
    }
}
public class Test {
    public static void main(String[] args) {
        Student stu1  = new Student("张三",18);
        Student stu2  = new Student("李四",29);
        Student stu3  = new Student("王五",20);

        System.out.println(stu1.compareTo(stu2));//-11
        System.out.println(stu2.compareTo(stu1));//11
    }
}
  • 当覆写Comparable接口之后,就可以进行排序
public class Test {
    public static void main(String[] args) {
        Student stu1  = new Student("张三",18);
        Student stu2  = new Student("李四",29);
        Student stu3  = new Student("王五",20);

       Student[] stu = new Student[] {stu1,stu2,stu3};
        Arrays.sort(stu);
//[Student{name='张三', age=18}, Student{name='王五', age=20}, Student{name='李四', age=29}]
        System.out.println(Arrays.toString(stu));
    }
}
  • 排序默认是升序排列,如果需要降序排列,需要修改compareTo()方法
 public int compareTo(Student o) {
        return o.age - this.age;
    }
  • 此时,就得到了降序排列
public class Test {
    public static void main(String[] args) {
        Student stu1  = new Student("张三",18);
        Student stu2  = new Student("李四",29);
        Student stu3  = new Student("王五",20);

       Student[] stu = new Student[] {stu1,stu2,stu3};
        Arrays.sort(stu);

//[Student{name='李四', age=29}, Student{name='王五', age=20}, Student{name='张三', age=18}]
        System.out.println(Arrays.toString(stu));
    }
}
  • Comparator比较器

 Comparator比Comparable更灵活,不需要修改类中的代码

public class Test {
    public static void main(String[] args) {
        Student stu1  = new Student("张三",18);
        Student stu2  = new Student("李四",29);
        Student stu3  = new Student("王五",20);
        Student[] stu = new Student[] {stu1,stu2,stu3};

        Arrays.sort(stu, new StudentCom());
//[Student{name='张三', age=18}, Student{name='王五', age=20}, Student{name='李四', age=29}]
        System.out.println(Arrays.toString(stu));

        Arrays.sort(stu,new StudentDesc());
//[Student{name='李四', age=29}, Student{name='王五', age=20}, Student{name='张三', age=18}]
        System.out.println(Arrays.toString(stu));

    }
}

class StudentCom implements Comparator<Student>{

    @Override
    public int compare(Student o1, Student o2) {
        return o1.getAge()-o2.getAge();
    }
}

class StudentDesc implements Comparator<Student>{

    @Override
    public int compare(Student o1, Student o2) {
        return o2.getAge()-o1.getAge();
    }
}

  • 使用Comparator将JDK的最小堆改造为最大堆
public class PriorityQueueTest {
    public static void main(String[] args) {
//通过构造方法传入比较器
        Queue<Student> queue = new PriorityQueue<>(new StudentCom());
        Student stu1  = new Student("张三",18);
        Student stu2  = new Student("李四",29);
        Student stu3  = new Student("王五",20);
        queue.offer(stu1);
        queue.offer(stu2);
        queue.offer(stu3);
      while (!queue.isEmpty()){
          System.out.println(queue.poll());

//Student{name='张三', age=18}
//Student{name='王五', age=20}
//Student{name='李四', age=29}

      }
    }
}
  •  当需要降序时,将  Queue<Student> queue = new PriorityQueue<>(new StudentCom());中的加粗部分改为
Queue<Student> queue = new PriorityQueue<>(new StudentDesc());
  • 也可以这样写,匿名内部类,就是创建一个Comparator接口的子类,这个子类只使用一次
 Queue<Student> queue = new PriorityQueue<>(new Comparator<Student>() {
                        @Override
            public int compare(Student o1, Student o2) {
                return o2.getAge() - o1.getAge();
            }
        });
  • 也可以这样写,Lambda表达式,函数式编程
 Queue<Student> queue = new PriorityQueue<>((o1,o2) -> o2.getAge() - o1.getAge());

==和equals的区别

  • ==

比较的是两者的值是否相等,如果比较的是两个基本类型,就是比较两个的数值是否相等。如果比较的是引用类型,要比较的是引用类型保存的地址

  • equals

比较两个对象是否相等,可以自己定义 

public class Test{
    public static void main(String[] args){
        Object o =new Object(){
            public boolean equals(Object obj){
                return true;
            }
        };
//true
        System.out.println(o.equals("“”"));
//true
        System.out.println(o.equals(123));
    }
}

在匿名内部类中覆写equals方法,不进行比较,是直接返回true的

Comparable和Comparator的区别

当一个类实现了Comparable接口,那么这个类就具备了比较两个对象的能力,但是Comparator是把两个对象的比较交给另外一个类,当前类是没有比较的能力的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习java的张三

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值