普通队列:FIFO(银行排队)
先进先出,元素按照入队的先后顺序进行出队操作
优先级队列:看起来是个队列,底层是基于堆的实现(医生给患者做手术,按照病情决定,严重的优先,病情相同,按照顺序)
按照元素间优先级的大小动态顺序出队
这和排序有何不同?
按照排序后的结果依次处理
操作系统的进程调度来说,底层就是维护了一个优先级队列。
操作 | 普通队列(基于链表) | 优先级队列(堆) |
入队 | O(1) | O(logn) |
出队(出最大值) | O(n) | O(logn) |
虽然对顶就是最大值,但是要删除堆顶元素,还要进行元素shiftDown操作
看到logn级别的时间复杂度,近乎一定是和"树"结构紧密相关。(此处不一定要真正构造二叉树)
快排和归并的递归本质过程是一个“递归”树,回溯算法大部分是和logn相关的时间复杂度,回溯的本质也是树。
JDK中的优先级队列默认是最小堆的实现,队首元素就是当前队列中的最小值。
元素间比较大小
比较两个自定义类型是否相等 ->覆写Object类提供的equals方法!
向上转型:
参数统一化,使用父类引用,无论是那个子类引用,都可以调用父类中已经定义好的方法,具体表现为啥样,就看子类方法覆写的内容了。 -> 多态性
天然发生的is a关系。Dog is an Animal.
能调用的方法要看父类,此时引用是父类的引用,只有父类中定义了相关方法才能使用。到底调用的是谁,要看子类是否覆写了。如果子类覆写了,则调用的一定是子类覆写 的方法,否则调用父类的方法。
向下转型:
子类名称 子类引用 = (子类名称)父类引用;//强制类型转换
Studnet stu = (Student) o;
若此时要调用只有student类中才具备的方法或属性时,就需要向下转型,将父类引用的外衣脱掉,还原为子类引用。
此时我们进行studnet对象的比较,比较student类中的name和age属性,这俩属性是student独有的,就需要向下转型为student引用。
name和age都是private修饰的属性,为什么这里可以还可以直接通过引用访问?
因为重写的方法在student内部。
比较两个自定义的对象谁大谁小 -> java.lang.Comparable
一旦一个类实现了Comparable接口,就表示该类具备了可比较大小的能力
int一共有三种情况取值
大于0:当前对象大于传入对象
等于0:当前对象=传入对象
小于0:当前对象小于传入对象
一旦一个自定义的类覆写了Comparable接口,就可以进行排序了!
Arrays.sort()排序默认是降序,我想要升序,该怎么做??
我们把compareTo方法改一下,改成大的反而小,小的反而大就行了。
看不懂别人代码时,最简单的办法就是找个例子带入运行一下!一切都迎刃而解啦~
假设现在这个排序有时候需要按照年龄升序排列,有时候又要按照年龄降序排列,应该怎么做?
频繁根据不同场景改已经写好的代码是大忌!
有可能改着改着就把自己改蒙蔽了。
java.util.Comparator ->比较器
需要比较的类并不需要实现此接口,而是有一个专门的类实现此接口,这个类就是为了进行student的大小比较。
Comparator相较于Comparable来说更加灵活,无需修改。要比较类的代码 -> 无侵入编程 -> 策略模式(根据不同的需求配置不同的比较器)
就是创建了一个Comparator接口的子类,这个子类只使用一次(匿名内部类)
匿名内部类,以下是简写,也叫Lambda表达式,函数式编程
面试题17.14,找出数组中最小的K个数,并返回这k个数。
最小或最大个** --->都是优先级队列(堆的应用)
取大用小,取小用大 -->找出最小的k个数,构造大根堆