20172310 2017-2018《程序设计与数据结构》(下)第八周学习总结

20172310 2017-2018《程序设计与数据结构》(下)第八周学习总结

教材学习内容总结

1.一、堆

  • 堆(heap):是具备两个附加属性的二叉树。一是堆是一颗彻底树(若是一棵二叉树是平衡的,即全部叶子都位于h或h-1层,其中h为log2n, 且n是树中的元素数目,且全部h层中的叶子都位于该树的左边,那么该树就被认为是彻底的。),二是对每一结点,它小于或等于(大于或等于)其左孩子和右孩子。
  • 小于或等于其左孩子和右孩子的是最小堆(minheap),结点大于或等于它的左右孩子是最大堆(maxheap), 其中的结点大于或等于它的左右孩子。关键概念html

  • 最小堆将其最小元素存储在该二叉树的根处,且其根的两个孩子一样也是最小堆。
    java

  • 堆的接口:git


1.二、addElement操做

  • addElement方法将给定的Comparable元素添加到堆中的恰当位置处,且维持该堆的彻底性属性和有序属性。因此完成addElement方法有两个步骤,一是将元素放入堆中,二是调整元素的位置,保持堆的性质。
    • 放入的位置:一个堆就是棵彻底树, 因此对于插入的新结点而言只存在一个正确的位置, 且它要么是h层左边的下一个空位置,要么是h+1层左边的第1个位置(若是h层是满的话)
    • 排序属性:第一将该新元素和其父亲的值进行比较,若是该新结点小于其双亲则将它们互换;而后重复,沿着树向上,直至该新元素要么是大于其双亲要么是位于该堆的根处。在堆实现中,咱们会对树中的最末个结点,进行跟踪记录。

1.三、 removeMin 操做

  • 最小元素是存储在最小堆的根处的,因此要作的就是返回根元素并用堆中的另外一元素替换它。
    • 替换:与addElement操做同样,是要维持该树的彻底性,那么只有一个能替换根的合法元素,那就是是存储在树中最末片叶子上的元素。
    • 重排:将该新根元素与其较小的孩子进行比较,且若是孩子更小则将它们互换。沿着树向下继续这过程,直到该元素要么位于某叶子中, 要么比它的两个孩子都小。

1.四、findMin操做

  • 堆中最小元素元素老是被存储在该树的根处,因此实现findMin方法只需经过返回存储在根处的元素。

2.一、使用堆: 优先级队列

  • 优先级队列(priority queue) 是遵循两个排序规则的集合。
    • 具备更高优先级的项目在先。
    • 具备相同优先级的项目使用先进先出方法来肯定其排序。
  • 优先级队列实现方式有两种使用队列列表或最小堆。虽然最小堆根本就不是一个队列,可是它却提供了一个高效的优先级队列实现。
  • 过程:建立个PriorityQueueNode对象,用来存储将被放置在队列中的元素、该元素的优先级、以及元素放进队列的顺序。而后,使用compareTo 方法,对优先级进行比较,而后在优先级相同的时候再对阶进行比较。

三、用链表实现堆

  • 由于咱们要求在插入元素后可以向上遍历该树,因此堆中结点必须存储指向其双亲的指针。
  • 堆接口中定义的方法用链表实现,实现的算法和逻辑就是上述所写的。
    • 链表实现中实例化一个HeapNode类的LastNode引用,来跟踪记录堆中的最末一片叶子。
    • addElement方法还调用了两个私有方法来实现上述的两个步骤,其操做的复杂度为2×log n +1+log n ,即O(log n)。
    • addElement方法中调用的第二个重排序的方法实际上并无执行双亲与孩子的完整互换,它只是把双亲元素往下平移到正确的插入点,其复杂度也是O(log n)。可是,它的确提升了效率,由于它减小了在堆的每一层上要执行的赋值次数。
    • removeMin方法同理,时间复杂度为2Xlogn+logn+1,即O(log n)。
    • findMin方法的时间复杂度为O(1)。

四、用数组实现堆

  • 在二叉树的数组实现中,树的根位于位置0处,对于每一结点n, n的左孩子将位于数组的2n+1位置处,n的右孩子将位于数组的2(n+ 1)位置处,所以咱们可以计算
    双亲和孩子的位置。
  • 数组实现的addElement方法必须首先检查可用空间,如须要,要对该数组进行扩容。
    • 与链表实现不一样,数组实现不须要肯定新结点双亲的步骤。
    • 数组实现的addElement操做的时间复杂度与链表实现的复杂度同样为1+log n或O(log n)。
  • 链表实现和数组实现的removeMin操做的复杂度同为O(logn),
  • findMin 操做与链表实现的同样, 其复杂度为O(1)。

五、使用堆:堆排序

  • 使用一个堆来对某个数字列表进行排序,只需将列表的每元素添加到堆中, 而后一次一个地将它们从根中删除。 在最小堆的情形下,排序结果将是该列表以升序排列。在最大堆的情形下,排序结果将是该列表以降序排列。
  • 对于堆的排序算法,咱们须要执行addElemcmt和removeElement两个操做n次,即列表中每一个元素一次。 所以,最终的复杂度为2XnXlogn,即O(nlog n)。

蓝墨云上作的一个练习就很清楚地显示了这个过程。

算法

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

  • 问题1:课本屡次说到完成一些操做例如:addElement和removeMin等操做,数组和链表实现的堆的复杂度是相同的,可是仍是说数组实现的效率更高,这是为何?数组和链表实现堆的优缺点分别是什么?数组

  • 问题1解决方案:
    用数组实现堆时,进行addElement操做不须要和链表同样从新肯定新节点双亲,removemin操做不须要肯定新的最末结点。数据结构

简单总结一下,用数组实现堆的好处有学习

优势:和顺序存储同样的
一、能够很方便找到孩子、双亲和兄弟,以及祖先和子孙
二、只须要存储数据元素,不须要另外存储元素的逻辑关系
三、物理结构和逻辑结构一致测试

  • 问题2:代码解读。下面这一段代码是用链表实现堆的addElement操做时的返回插入结点双亲的那个节点的引用,可是我分状况讨论的过程当中一直出现理解不了的地方。
private HeapNode<T> getNextParentAdd()
    {
        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;
    }
  • 问题2解决方案:第一遍看的时候,把本身的书画的乱七八糟的都没有理解这些代码的意思,

而后就去问馨雨同窗,这些代码的意思,结果讨论讨论着,馨雨馨雨就被我问蒙了,O(∩_∩)O,后来,发现是咱们理解错了lastNode结点,“插入结点的双亲结点”,以前一直理解的是将要插入的结点的双亲结点,其实lastNode是最后一片叶子结点,状况以下:

设计

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

  • 问题1:

ArrayHeap类的代码书上是有给出的,而后本身写了一个测试类,结果发现出现了这样的问题3d

  • 问题1解决方案:想要进行调试看一下,结果发现

    (这个问题我不知道是为何发生的o(╥﹏╥)o)

而后又仔细思考了一下代码,在代码中将最后一个元素赋值给了root结点,可是缘由是并无将叶结点删除,因此接下来从新调平衡的时候,最后的那个位置并进行操做,因此出现了重复。

代码托管

(statistics.sh脚本的运行结果截图)

上周考试错题总结

  • 错题1及缘由,理解状况

    What type does "compareTo" return?
    A
    .
    int
    B
    .
    String
    C
    .
    boolean
    D
    .
    char

解析:compareTo()方法确实是String类中的一个,可是compareTo()的返回值是int。

它先比较对应字符的ASCII码,如字符串的某字符与参数的某字符不等,则结束比较,返回它们ASCII码的差值。直至字符串的字符或参数的字符 有一方全比较完,此时比较字符串的长度差并返回。

结对及互评

点评:

  • 本周结对学习状况
  • 博客中值得学习的或问题:

    • 挺逗的,能够用来吸引目光。博客的页面又进行了修改,挺好看的。
  • 代码中值得学习的或问题:
    • 设计的思路很清晰,不像我同样老是很奇葩,^_^。

点评过的同窗博客和代码

其余(感悟、思考等,可选)

这周又是Java课多到爆表的双周,咱们又开始完成实验二了,并且这周老师还让咱们组了个队,要完成一个Java项目的开发,ε=ε=ε=(#>д<)ノ,难。
这个学期愈来愈注重代码的编写能力,也接触到了不少的新的算法和知识点,就像这个礼拜学的堆,但愿本身接下来的课程要继续努力。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积)
目标 5000行 30篇 400小时
第一周 0/0 1/1 10/10
第二周 326/326 1/2 18/28
第三周 784/1110 1/3 25/53
第四周 2529/3638 2/5 37/90
第五周 1254/4892 2/7 20/110
第六周 1403/6295 2/9 32/142
第七周 1361/7656 1/10 35/177
第八周 2750/10406 2/12 32/209
  • 计划学习时间:30小时

  • 实际学习时间:32小时

  • 改进状况:这周是双周,Java课比较多,课程内容也比较多,保持了良好的学习进度和时间。

参考资料

相关文章
相关标签/搜索