20172323 2018-2019-1 《程序设计与数据结构》第八周学习总结

20172323 2018-2019-1 《程序设计与数据结构》第八周学习总结

教材学习内容总结

本周学习了第12章优先队列与堆php


  • 12.1 堆
  • 堆是具备两个附加属性的一棵二叉树,它是一棵彻底树,对于每一结点,它小于或等于其左孩子和右孩子,这样定义下的堆是最小堆,若是对于每一结点,它大于或等于其左孩子和右孩子,那么它就是最大堆。
  • 最小堆将其最小元素存储在该二叉树的根处,且其根的两个孩子一样也是最小堆。
操做 说明
addElement 将给定元素添加到该堆中
removeMin 删除堆的最小元素
findMin 返回一个指向堆中最小元素的引用
  • 如图是一个最小堆
    html

  • addElement方法将给定的Comparable元素添加到堆中的恰当位置处,且维持该堆的彻底性属性和有序性属性node

    若是一棵二叉树是平衡的,及全部叶子都位于h或者h-1层,其中h为log2n,n是树中的元素数目,以及全部h层中的叶子都位于该树的左边,那么该树就被认为是彻底的。由于堆是一棵彻底树,因此对于新插入的结点只存在一个正确的位置,要么是h层左边的下一个空位置,要么就是h+1层左边的第一个位置(若是h层是满的话)git

  • 新结点添加以后,将考虑堆的排序性。,该结点将于它的双亲结点进行比较,若是新结点小则要与双亲结点进行互换,以后再沿树往上进行比较直至新值大于双亲或者位于根结点。
  • 在堆实现中,咱们会对树中的最末一个结点(最末一片叶子)进行跟踪记录。

    2添加到堆以后,将于其双亲进行比较上浮直至堆知足其顺序属性
  • removeMin操做将删除最小堆中的最小元素并返回他,最小堆中的元素便是它的根结点,为了保持树的合法性,须要有一个能替换根的合法元素,且它是树中最末一片叶子上的元素。将最末一片叶子移至根处以后,又须要将该堆进行从新排序。排序方法须要将该结点与最小孩子进行比较而后逐渐下沉到合适的位置。借用上图,若是将根结点1删去,那么最末叶子6就将成为新的根结点,它将与二、5进行比较最终落在5如今的位置,而2将成为新的根结点。web


  • 12.2 使用堆:优先级队列
  • 优先级队列就是遵循两个排序规则的集合。一是具备更高优先级的项目在先,二是具备相同优先级的项目使用先进先出方法肯定其排序。
  • 虽然最小堆根本就不是一个队列,可是他却提供了一个高效的优先级队列实现

  • 12.3 用链表实现堆
  • 堆中结点必须存储指向其双亲的指针。
  • 链表实现addElement操做的时间复杂度为O(logn)
  • removeMin操做的时间复杂度一样为O(logn)。
  • findMin操做时间复杂度为O(1)

  • 12.4 用数组实现堆
  • 堆的数组实现比链表实现更为简洁。
  • 在二叉树的数组实现中,树的根位于位置0处,对于每一结点n,n的左孩子将位于数组的2n+1
    处,n的右孩子将位于数组的2(n+1)位置处
  • 数组实现不须要肯定新结点双亲,时间复杂度与链表实现相同,但数组实现效率更高
  • 链表实现与数组实现的removeMin操做的复杂度同为O(logn)

  • 12.5 使用堆:堆排序
  • 堆排序的由两步构成:添加列表的每一个元素,而后一次删除一个元素
  • 堆排序的复杂度为O(nlogn)

教材学习中的问题和解决过程

  • 问题1:链表实现堆的过程当中的addElement操做第一步要肯定要插入结点的双亲,为何在最坏的状况下要从堆的右下结点遍历到根结点以后还要再从根结点遍历到堆的左下结点?数组

  • 问题1解决方案:这个问题我思考了小半个小时,添加的第一步须要肯定插入结点的双亲,由于须要比较双亲结点的值与新结点的值,决定新结点是否要上浮。因此最坏的状况应该是新结点一直上浮到根结点,此时按最小堆的定义来看,添加元素这一操做应该是中止了,由于堆顶是最小元素了,它的左孩子和右孩子的值都应该比它要小,因此不须要继续遍历它的左孩子直到左下结点了吧。和同窗讨论以后,才发现个人理解错在哪里了。它这里指的是遍历的最坏状况须要从右下结点一直到根再到左下结点,而不是结点互相之间的比较须要让结点上浮以后再次下沉(事实上跟我分析的同样,他也没法作到)。它这里指的是查找肯定新结点的双亲结点的最坏状况

    如上丑图,添加元素时恰好碰见满树的状况,须要从右下最后一片叶子开始找起,一直到左下结点,才最终肯定要插入的元素的双亲结点。数据结构


  • 问题2:对书上代码getNextParentAdd方法的理解
  • 问题2解决方案
HeapNode<T> result = lastNode;
        while ((result != root) && (result.getParent().getLeft() != result))
            result = result.getParent();
        if (result != root)
            if (result.getParent().getRight() == null)
                result = result.getParent();
            else {
                result = (HeapNode<T>) result.getParent().getRight();
                while (result.getLeft() != null)
                    result = (HeapNode<T>) result.getLeft();
            }
        else
            while (result.getLeft() != null)
                result = (HeapNode<T>) result.getLeft();

        return result;

首先教材讲到,这是一个返回指向插入结点的双亲结点的引用。因此就容易理解到,这个方法就是肯定新插入结点的双亲结点。也就经过此来决定新添加元素的位置。
一开始,新设一个变量result指向lastNode,即指向最后一片叶子的引用。
接下来经过判断最后一片叶子的状况来肯定插入结点的双亲结点,当最后一片叶子不是根结点且同时不是左孩子的时候,就将result的父结点付给result,直到不知足两个条件之一跳出循环。当最后一片叶子是根结点时,已经肯定了新结点的双亲结点,能够进入下一步,而若是最后一片叶子是右结点,就说明当前父结点是满的,不能再在当前父结点下添加新元素,因此将result指向result的父亲,方便寻找一个没有满的父结点。下一步,此时result跳出while循环,要么它是根结点,要么它是左孩子。若是它是左孩子,即进入if语句内,判断它的兄弟结点是否为null,若是返回true,那么新添加元素的双亲结点就肯定了是result的父结点,而新结点将做为result的右孩子添加到堆中,若是返回false,result将指向这个右孩子,并找到它的最左下的位置添加。若是result是指向根结点的,那么也一直循环到它的最左下位置,添加新元素。
这个问题的解决参考了于欣月同窗的博客,她在解释时运用了图文结合的形式,对我理解该问题起了很大帮助ide


代码调试中的问题和解决过程

  • 问题1:测试LinkedHeap类,实现层序输出、前序中序后序各类输出,很不巧的是它出现了乱码的状况
    学习

  • 问题1解决方案:这个问题的出现充分说明我还没能掌握迭代器的精髓,首先方法的使用就是彻底错误的,我还把它看成简单的toString方法在加以使用。因此天然输出不来须要的结果,标准的应该是如图,先设置一个迭代器的对象,经过for循环一个一个调用迭代器里的内容,如图
    测试

代码托管

上周考试错题总结


  • In removing an element from a binary search tree, another node must be ___________ to replace the node being removed.
    A .duplicated
    B .demoted
    C .promoted
    D .None of the above
  • 解析:从二叉查找树中删除一个元素时,必须推选出另外一个结点来代替要被删除的那个结点
    。demoted意思是降级的,promoted是升级的,从概念来看,替代元素应该是该结点的中序后继者,因此该是c。

  • The Java Collections API provides two implementations of balanced binary search trees, TreeSet and TreeMap, both of which use a ___________tree implementation.
    A .AVL
    B .red/black
    C .binary search
    D .None of the above
  • 这好像是13章的内容乱入了吧,TreeSet和TreeMap类使用的是红黑平衡二叉查找树

  • The best comparison sort in terms of order is:
    A .O(1)
    B .O(n)
    C .O(log(n))
    D .O(nlog(n))

  • Linear search has logarithmic complexity, making it very efficient for a large search pool.
    A .true
    B .false
  • 线性查找具备线性时间复杂度O(n)。

  • Bubble, Selection and Insertion sort all have time complexity of O(n).
    A .true
    B .false
排序方法 时间复杂度
选择排序 O(n^2)
插入排序 O(n^2)
冒泡排序 O(n^2)

  • Insertion sort is an algorithm that sorts a list of values by repetitively putting a particular value into its final, sorted, position.
    A .true
    B .false
  • 插入排序经过反复地将某一特定值插入到该列表的某个已排序的子集中来完成对列表值的排序。每个值只须要插入一次,而不是重复地插入。

结对及互评

  • 博客中值得学习的或问题:
    • 在个人鞭策与督促之下,某同窗的博客又恢复到了以往的超高水平。(他在教材问题中提到了一个

      实现优先级队列的二叉堆、d堆、左式堆、斜堆、二项堆都是什么意思?

我翻了一下书,好像没有找到哪里提到了这些概念,因此若是是查找的资料里提到的,但愿也能贴出连接来,让我学习学习,不至于落下太多

  • 方艺雯的博客写的很棒,提出了不少我没考虑过的问题。

  • 基于评分标准,我给谭鑫的博客打分:6分。得分状况以下:
    正确使用Markdown语法(加1分)
    模板中的要素齐全(加1分)
    教材学习中的问题和解决过程, 一个问题加1分
    代码调试中的问题和解决过程, 三个问题加3分

  • 基于评分标准,我给方艺雯的博客打分:8分。得分状况以下
    正确使用Markdown语法(加1分):
    模板中的要素齐全(加1分)
    教材学习中的问题和解决过程, 两个问题加2分
    代码调试中的问题和解决过程, 四个问题加4分

  • 本周结对学习状况
  • 上周博客互评状况

其余

这周的教材学习比较容易,因此花的时间相对较少,可是实验使人难受。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 0/0 1/1 8/8
第二周 470/470 1/2 12/20
第三周 685/1155 2/4 10/30
第四周 2499/3654 2/6 12/42
第六周 1218/4872 2/8 10/52
第七周 590/5462 1/9 12/64
第八周 993/6455 1/10 12/76
第九周 1192/7467 2/12 10/86

参考资料

相关文章
相关标签/搜索