关于findMax()函数的一个小小问题
来源:8-4 从堆中取出元素和Sift Down
DorJake
2019-05-06
感觉findMax()是不是应该私有的比较好,感觉有可能会破坏堆的结构。
比如用一个堆存放Student类
MaxHeap<Student> maxheap = MaxHeap<>();
之后往maxheap中放入Student对象
然后取出最大的Student对象,并且更改其年龄
Student s = maxheap.fandMax(); s.setYear(0);
假如student对象的大小比较就是和其year属性相关。
经过上述的操作之后这个大顶堆的结构就被破坏了,因为改变最大元素的属性之后并不会进行Shif Down操作。
解决方法我想的是定义两个函数,一个fianMax()是私有的和教程中一样。还有一个getMax()为公有的开放给外部调用,返回的是最大元素的克隆。不知道是不是有其它方法。
写回答
1回答
-
大赞。
你的考虑是对的。但是,在Java中,无法通过访问限制的问题解决(C++中可以解决)。你的clone的方法是ok的,但是增大了开销。
事实上,Java标准库中的数据结构,有同样的问题。以PriorityQueue为例(底层就是堆),你可以实验如下代码:
// 创建一个学生类 public class Student implements Comparable<Student>{ public String name; public int score; public Student(String name, int score){ this.name = name; this.score = score; } // 学生类可以按照分数做比较 @Override public int compareTo(Student another){ return another.score - score; } @Override public String toString(){ return this.name + " " + String.valueOf(this.score); } }然后,实验如下Main:
import java.util.PriorityQueue; public class Main { public static void main(String[] args) { PriorityQueue<Student> pq = new PriorityQueue<>(); pq.add(new Student("A", 60)); pq.add(new Student("B", 100)); pq.add(new Student("C", 80)); // 打印优先队列的第一名,应该是B同学,100分嘛 System.out.println(pq.peek()); // 现在,把第一名取出来 Student topStudent = pq.peek(); // 他的成绩判错了,其实是15分,直接修改 topStudent.score = 15; // 再打印优先队列的第一名,还是B同学。可却是15分 System.out.println(pq.peek()); } }所以,这个问题在Java语言中是一个设计困境。看你的取舍了。当前的设计,就是需要调用者保证不直接修改优先队列中的引用内容。这就好比用户调用数组元素,需要保障数组索引不越界;调用出栈或者出队操作,需要保障栈或者队不为空一样:)
继续加油!:)
50
相似问题