20172316 2018-2019-1《程序设计与数据结构》第八周学习总结
教材学习内容总结
第十二章 堆
堆:
堆是具有两个附加属性得的一棵二叉树:
- 它是一棵完全树;
- 对每一节点,它小(大)于或等于其左孩子和右孩子。
堆的分类:按照堆中元素排列规律将堆分为两类:
-
最小堆(minheap),本章介绍中默认的堆的类型,对每一节点,它小于或等于其左孩子和右孩子
-
最大堆(maxheap),与最小堆相反(对每一节点,它大于或等于其左孩子和右孩子)
优先级队列(priority queue):
排序规则:
- 具有更高优先级的项在前;
- 具有相同优先级的项目按照先进先出方法来确定排序。
回顾知识点:完全树,树最底层的叶子都在树的左边
堆接口的方法(最小堆)
操作 | 说明 |
---|---|
addElement | 将给定元素添加到该堆中 |
removeMin | 删除堆中的最小元素 |
findMin | 返回一个指向堆中最小元素的引用 |
教材学习中的问题和解决过程
- 创建一个堆之后进行多次
addElement()
操作添加元素后,还需要进行重排序?
选择数组addElement()分析,较为简短:
public void addElement(T obj)
{
if (count == tree.length)
expandCapacity();
tree[count] = obj;
count++;
modCount++;
if (count > 1)
heapifyAdd();
}
private void heapifyAdd()
{
T temp;
int next = count - 1;
temp = tree[next];
while ((next != 0) &&
(((Comparable)temp).compareTo(tree[(next-1)/2]) < 0))
{
tree[next] = tree[(next-1)/2];
next = (next-1)/2;
}
tree[next] = temp;
}
检查代码,发现:在插入过程中addElement()
方法引用了heapifyAdd()
方法,addElement()
方法仅作插入,将指定元素放到最末节点,如果不进行重排序,堆就不一定会符合小项在上的规则。
重排序和插入是同时进行的,而不是我之前理解的:先插入后排序
同样的问题,removeMin()
方法删除最小元素(最顶端),要维持堆的完全性,替换它的元素是最末的元素,此时也需要进行重排序:
private void heapifyRemove()
{
T temp;
int node = 0;
int left = 1;
int right = 2;
int next;
if ((tree[left] == null) && (tree[right] == null))
next = count;
else if (tree[right] == null)
next = left;
else if (((Comparable)tree[left]).compareTo(tree[right]) < 0)
next = left;
else
next = right;
temp = tree[node];
while ((next < count) &&
(((Comparable)tree[next]).compareTo(temp) < 0))
{
tree[node] = tree[next];
node = next;
left = 2 * node + 1;
right = 2 * (node + 1);
if ((tree[left] == null) && (tree[right] == null))
next = count;
else if (tree[right] == null)
next = left;
else if (((Comparable)tree[left]).compareTo(tree[right]) < 0)
next = left;
else
next = right;
}
tree[node] = temp;
}
removeMin()方法涉及到最末和顶部元素替换,重排序的过程也会相对复杂。
代码调试中的问题和解决过程
- “既然用数组实现堆时,使用了数组进行储存,为什么不能直接用这样的方法来导入元素↓?”
public void ArrayToHeap(T[] array) {
tree = array;
count = tree.length + 1;
}
后面产生了一系列问题,但是使用书本上的addElement()
方法插入时则不会出错,后来仔细研究addElement()
才发现问题所在:直接导入的数组不一定符合堆的性质,而使用addElement()
方法由于重排序的存在可以很好地解决这一问题。
代码托管
(statistics.sh脚本的运行结果截图)
上周考试错题总结
-
Insertion sort is an algorithm that sorts a list of values by repetitively putting a particular value into its final, sorted, position.
答案:false
)并不是直接放入最终排序位置。 -
There are only two ways that a tree, or any subtree of a tree, can become unbalanced: through the insertion of a node or through the deletion of a node.
答案:true
)书中原话。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 0/0 | 1/1 | 6/6 | |
第二周 | 771/771 | 1/2 | 16/22 | |
第三周 | 562/1233 | 1/3 | 15/37 | |
第四周 | 1503/2736 | 2/5 | 15/52 | |
第五周 | 1152/3888 | 1/6 | 10/62 | |
第六周 | 787/4675 | 1/7 | 10/72 | |
第七周 | 1214/5889 | 1/8 | 9/81 | |
第八周 | 1534/7423 | 1/9 | 9/90 |
结对互评
参考资料
- 《Java程序设计教程(第八版)》电子工业出版社
- 《使用码云和博客园学习简易教程》
- 《使用开源中国(码云)托管代码》
- 数据结构(一) 单链表的实现-JAVA