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

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

一、教材学习内容总结

相信其它很多同学都是以小顶堆来介绍这一章内容,所以我将以大顶堆来介绍这章内容。

1.1 堆的简单介绍:

  • 堆的定义:(大顶堆

    • 堆实际上是一棵完全二叉树。
    • 堆满足两个性质:
      1. 堆的每一个父节点都大于其子节点;
      2. 堆的每个左子树和右子树也是一个堆。
  • 堆的分类:
    • 堆分为两类:

      1. 最大堆(大顶堆):堆的每个父节点都大于其孩子节点;
      2. 最小堆(小顶堆):堆的每个父节点都小于其孩子节点;
    • 例子:

  • 堆的操作:
    • 堆的定义是二叉树的拓展,因此他也继承了二叉树的所有操作。
    • 操作列表(大顶堆为例):
    操作 说明
    addElement() 将给定元素添加到该堆中去
    removeMax() 删除堆中最大的元素
    findMax() 返回一个指向堆中最大元素的引用
  • addElement操作:
    • addElement方法将给定的Comparable元素添加到堆中的恰当位置,且维持该堆的完全属性和有序属性。
    • 因为堆是一棵完全二叉树,因此对于新插入的节点而言,就只有一个正确的位置,要么是h层左边的下一个空位置,要么是h+1层的第一个位置(此时h层已经装满了)。
    • 如下图:它有这两个位置可插入:
    • 通常在堆的实现中,我们会对二叉树的最后一片叶子进行跟踪记录。
    • 最大堆的插入:
  • removeElement操作:
    • 对于大顶堆而言,删除最大元素即删除二叉树的根结点,如果删除根结点而要想维持堆的完全性,必须与最后一片叶子进行交换位置。
    • 交换位置后,必须进行重排序、以维持堆的第二个属性:排序。
    • 用图表示下过程:
  • findMax操作

    findMax操作将返回一个指向该最大堆中最大元素的引用,也就是根结点的引用。所以实现这一操作只需返回储存在根结点的元素即可。

1.2使用堆:优先级队列。

  • 我们先来举个例子来感受下优先级队列。

    • 生活中,排队时讲究女士优先。
    • 游戏中,抽奖人民币玩家获得好东西的概率更大!
  • 好,我们现在来说什么是优先级队列:
    • 具有更高优先级的项目优先,比如女士、人民币玩家。
    • 具有相同优先级的项目使用先进先出的方法 确定其排序。
  • 虽然最大堆根本就不是一个队列,但是他提供了一个高效的优先级队列实现。
  • 关键代码:

    在我看来,这个比较的代码是重中之重的。


 public int compareTo(PrioritizedObject obj)
    {
      int result;

      if (priority > obj.getPriority())
          result = 1;
      else if (priority < obj.getPriority())
          result = -1;
      else if (arrivalOrder > obj.getArrivalOrder())
          result = 1;
      else
          result = -1;

      return result;
    }

1.3 用链表实现堆:

  • 因为我们需要再插入元素后能够向上遍历树,因此结点中需要一个指向双亲结点的指针
   public class HeapNode<T> extends BinaryTreeNode<T>
{
    public HeapNode<T> parent;//指向双亲的指针。

    public HeapNode(T obj)
    {
        super(obj);
        parent = null;
    }
}    
  • 我们还需要一个能够跟踪该堆最后一片叶子 的指针:

    public HespNode lastNode;

  • 最大堆的各种操作:
    • addElement操作:

      • addElement操作完成三个任务:

        1. 再恰当位置添加一个元素。
        2. 对堆进行重排序。
        3. 将lastNode指针重新指向新的最末结点。
      • addElement操作的时间复杂度为:O(log n)
    • removeMax操作:
      • removeMax主要完成三个操作:

        1. 将最后一片叶子结点与根结点交换位置。
        2. 对堆进行重排序。
        3. 返回初始根元素。
      • removeMax操作的时间复杂度为:O(log n)
    • findMax操作的时间复杂度为O(log n)

      1.4用数组实现堆:

  • 堆的储存一般都是用数组实现的。
  • 堆是基于二叉树实现的,在二叉树的数组视线中,对于任一索引值为n的结点,其左结点在2n+1的位置右结点在2n+2的位置
  • 用数组实现堆的操作与用链表实现堆的操作步骤一样。但值得注意的是:链表实现和数组实现的addElement操作时间复杂度虽然都为O(log n),,但实际上链表更快点。

1.5 使用堆:堆排序。

排序方法有两个部分构成:添加列表的每个元素、一次删除一个元素。

堆排序的时间复杂度为O(log n).

  • 进入实战:还记得上次的一个实验,给我们一个数组没让我们形成一个大顶堆,之后让我们排序:现在让我们整理一下思路:

    • 首先给出我们一个数组:[45,36,18,53,72,30,48,93,15,35]
    • 然后我们应该按照它们的索引形成一个二叉树:
    • 然后重排序,得到一个大顶堆:

    • 每轮排序的结果可以这样表达:
    public class test {
     public static void main(String[] args) {
         BigArraryHeap<Integer> temp=new BigArraryHeap<Integer>();
         int[] list={36,30,18,40,32,45,22,50};
         Object[] list2 = new Object[list.length];
    
         //将数组中的元素添加到大顶堆中
         for (int i = 0; i < list.length; i++)
             temp.addElement(list[i]);
    
         System.out.println("大顶堆的输出结果为:"+ temp);
         System.out.println();
    
         for(int n = 0; n < list2.length; n++){
             list2[n] = temp.removeMax();
             String result = "";
             for(int a = 0; a <= n; a++){
                 result += list2[a] + " ";
             }
             System.out.println("第" + (n+1) + "次排序:" + temp + " ~ " + result);
         }
    
         System.out.println();
    
         System.out.print("最后排序结果: ");
         String result = "";
         for(int m = 0; m < list.length; m++){
             result += list2[m] + " ";
         }
         System.out.println(result);
       }
     }
    • 运行结果为:

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

  • 问题1:如何理解这段话,该怎样实现?

    通常在堆的实现中,我们会对二叉树的最后一片叶子进行跟踪记录。

  • 问题1解决方案:

    就是在对堆进行删除操作的时候需要将根结点与最后一片叶子结点进行交换位置,所以每一次操作都得更新lastNode结点。

  • 问题2:书上介绍了用数组实现的堆排序,那么链表实现的堆排序应该怎样排序?
  • 问题2解决方案:书上数组对对进行排序是写了一个方法,当想要进行排序的时候直接调用这个方法就OK,而我们选在在测试类里面直接进行排序,使用最大堆,取出最大堆输出,然后就可以直接输出。

    如图:

  • 问题三:在网上搜寻有关于书上的资料室,出现了这么一个尴尬场面:

    之后我点进去看了一下:

原来是讲解了有关:栈内存和堆内存。
讲了这么个些东西,来潦草的总结下:

  • ava把内存划分成两种:一种是栈内存,一种是堆内存
    在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。
  • 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。 - 堆内存用来存放由new创建的对象和数组。
  • 在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。
  • 在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。
  • 引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。
    (大概就看懂了这么多)

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

  • 问题1:如何用堆构建一个队列、栈?
  • 问题1解决方案:

    首先我们得知道我们必须运用优先级堆,并且每一次添加元素,优先级都加一(从0开始)。

  • 然后我们根据队列、栈的特点来输出
    • 队列是一种先进先出的结构,所以我们只要使用最小堆中的removeMin方法即可输出最先进去的元素。
    • 栈是一种先进后出的结构,所以我们只要使用最大堆中的removeMax方法即可输出最后面进去的元素,因为它的优先级高,所以他在前面输出。
    • 结果
  • 问题二:符合把一个Object型数据转化为char类型数据?
  • 原问题是这样的我需要把Object operator= +转化为char型数据,但是如果直接转,比如这样(char)operator是会抛出CalssCastException错误的!
  • 之后解决办法是先转化成String 然后再转化成char类型。
//像这样:
String a = String.valueOf(ope.pop());//ope.pop()出来的是一个Object型数据。
           operator = a.charAt(0);

代码之家

上周考试错题总结

第十章错题

  • 错题1及原因:

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

    错误原因:comparaTo方法返回的是 -1,0,1
    return "a".comparaTo("b")>0false or ture

    第十一章错题


  • 第十二章错题

    Since a heap is a binary search tree, there is only one correct location for the insertion of a new node, and that is either the next open position from the left at level h or the first position on the left at level h+1 if level h is full.
    A .True
    B .Flase

    错误原因:堆是一棵完全二叉树、不是一颗二叉搜索树。自己瞎了眼!!!!

    点评模板:

    博客或代码中值得学习的或问题:

    • 内容很详细,把堆介绍的很透彻,
    • 运用丰富的图片表达思想、比如插入、删除结点的介绍。
    • 提出问题有点少。

      点评过的同学博客和代码

  • 本周结对学习情况
    • 20172310
    • 结对学习内容
      • 第十二章内容:堆、优先级队列
      • 实验二:树的综合运用
  • 上周博客互评情况
    - 20172302
    - 20172308
    - 20172310
  • ...

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

    这一章比起前面相对比较简单,但自己不能松懈.哎,比较难受的是这两天的假期都要贡献给博客了~~~~~o(╥﹏╥)o

学习进度条(上学期截止7200)

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 260/0 1/1 05/05
第二周 300/560 1/2 13/18
第三周 212/772 1/4 21/39
第四周 330/1112 2/7 21/60
第五周 1321/2433 1/8 30/90
第六周 1024/3457 1/9 20/110
第七周 1024/3457 1/9 20/130
第八周 643/4100 2/11 30/170

参考资料

1.优先队列
2.堆排序
3.java 各种数据类型之间的转化
4.java中的栈与堆

原文地址:https://www.cnblogs.com/dky-wzw/p/9940410.html

时间: 2024-07-29 23:41:25

2017-2018-20172309 《程序设计与数据结构》第八周学习总结的相关文章

20182304 《数据结构与面向对象程序设计》第七八周学习总结

20182304 <数据结构与面向对象程序设计>第七八周学习总结 教材学习内容总结 时间复杂度分析:时间复杂度越低,程序运行效率越高.时间复杂度又称为算法的阶,符号计为O(),它由增长函数的主项决定.可以通过数学方法求出增长函数从而确定程序的时间复杂度 线性集合:集合中的元素按直线方式组织.如:队列集合.栈集合 栈是一种线性数据结构,采用后进先出(Last in,first out)的方法处理元素,我们学习使用了数组和链表来实现栈 链表:链表是链式结构的一种.在链表中,对象引用变量也可称为指针

20172322 2017-2018-2 《程序设计与数据结构》第二周学习总结

20172322 2017-2018-2 <程序设计与数据结构>第二周学习总结 教材学习内容总结 了解了print与println的区别 了解了字符串的拼接可以用+来完成 了解了转义字符的使用 学会了使用赋值 学会使用部分算术运算符 学会了使用Scanner来实现交互性 教材学习中的问题和解决过程 问题1:在最初接触赋值时对foalt和double的赋值范围不了解 问题1解决方案:使用万能的度娘后看到一个高赞答案后有了了解 问题2:在提前预习时看到2.7图形后敲入的代码无法执行 问题2解决方案

20172328《程序设计与数据结构》第二周学习总结

20172328李馨雨<程序设计与数据结构>第二周学习总结 又到周五,李馨雨同学要开始写博客了.让我们开始吧!(????) 教材学习内容总结 1.首先是String类定义的字符串,然后是print和println的区别.转义字符的学习.(让我印象深刻的\b[回车符]在字符串结尾不显示哈哈,及其更新的\t[换行符],还有在课堂上真正明白了什么是回车.) 2.了解变量.常量.赋值语句.变量:保存数据的内存单元.常量:坚定自己不会变的数据!除非你用java的反射(有点复杂,改权限.去修饰符等等.没实

学号20172328《程序设计与数据结构》第九周学习总结

学号20172328<程序设计与数据结构>第九周学习总结 教材学习内容总结(异常和递归) 第11章:异常 1.[异常处理]: 一个异常:是一个定义非正式情况或错误的对象,由程序或者运行时环境抛出,可以根据需要捕获和处理. 错误:错误类似于异常,但是错误代表不可恢复的问题并且必须捕获处理. 2.[处理异常的三种方法]:①根本不处理异常②当异常发生时处理异常③在程序的某个位置集中处理异常. 3.[未捕获的异常]:如果程序中不处理异常,则程序将非正常的终止运行,并产生关于描述在何处发生什么异常的信息

20172326 《程序设计与数据结构》第九周学习总结

学号 20172326 <程序设计与数据结构>第九周学习总结 教材学习内容总结 异常(exception):定义非正常情况下或错误的情况的对象,由程序或运行时环境抛出,可根据需要进行相应的捕获处理. 异常与错误的区别:错误代表不可恢复的问题并且必须捕获处理.而异常可以忽视,或者使用try语句处理,或调用更高级的方法. 可检测异常与不可检测异常:可检测异常必须由方法捕获,或者必须在可能抛出或传递异常方法的throws子句中列出来.在方法定义的声明头中追加一条throws子句.不可检测异常不需要使

20172322 2017-2018-2 《程序设计与数据结构》第九周学习总结

20172322 2017-2018-2 <程序设计与数据结构>第九周学习总结 教材学习内容总结 异常 学会了使用try-catch来实现未捕获的异常的处理.可以使得异常被捕获进而不导致程序出现错误退出.使用try写入可能产生异常的语句,使用catch来编写在捕获异常后继续执行的代码(可以为空). "未捕获的异常"指在编译过程中不会被编译软件显示异常但是在运行时会出现异常导致程序直接退出,例如:"ArithmeticException"."In

20172311 2017-2018-2 《程序设计与数据结构》第九周学习总结

20172311 2017-2018-2 <程序设计与数据结构>第九周学习总结 教材学习内容总结 本周对异常和递归进行了学习 异常的处理方式有两种:一种是直接抛出,并从异常处终止程序:另一种是捕获并处理异常,从而使程序继续运行. 捕获和处理异常主要运用try-catch语句. 通过继承Exception类可以自定义一个新的异常 处理IO异常的常用方法是抛出异常. 对于某些问题,递归是最精炼和适当的解法,但对于其他问题,递归则不如迭代方法直接. 教材学习中的问题和解决过程 问题:什么是IO操作

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

20172327 2018-2019-1 <程序设计与数据结构>第九周学习总结 教材学习内容总结 第十五章 图 无向图 1.图的概念(非线性结构):允许树中每个结点与多个结点相连,不分父子结点. 2.图由顶点和边组成. 顶点由名字或标号来表示,如:A.B.C.D: 边由连接的定点对来表示,如:(A,B),(C,D),表示两顶点之间有一条边. 3.无向图:顶点之间无序连接. 如:边(A,B)意味着A与B之间的连接是双向的,与(B,A)的含义一样. 4.邻接(邻居):两个顶点之间有边连接. 5.自

《程序设计与数据结构》第九周学习总结

学号 20172326 <程序设计与数据结构>第九周学习总结 教材学习内容总结 图:图(Graph)是一种复杂的非线性结构,在图结构中,每个元素都可以有零个或多个前驱,也可以有零个或多个后继,也就是说,元素之间的关系是任意的.与树的区别在于树中的一个结点只有一个前驱,也就是说只有一个父结点.但图中的顶点(结点)是没有这种限制关系的. 无向图:边为无需结点对的图.也就是说,现有两个顶点A.B.(A,B)与(B,A)效果相同.当两个顶点之间有边连接,也就是说这两个顶点是邻接的,也称作邻居.一个顶点

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

20172333 2018-2019-1 <程序设计与数据结构>第九周学习总结 教材学习内容总结 <Java软件结构与数据结构>第十五章-图 一.无向图 ①无向图的定义 图是由结点与结点相连接构成的,与树类似.这些结点被常常称作顶点(vertice),这些顶点的连接叫做边(edge). 无向图(undirected graph)是一种边为无序结点对的图. 两个顶点之间有一条连通边的顶点,我们称作它们为领接的(adjacent).这两个顶点也叫作邻居(neighbor),自己是自己的