建立一个类名为FilePro的Java二叉树的建立Bean,里面包含filePath,fileName, ab

基础知识总结(超级经典)

    1明确需求。我要做什么

    2,分析思路我要怎么做?1,2,3

    3,确定步骤每一个思路部分用到哪些语句,方法和对潒。

    4代码实现。用具体的 代码把思路体现出来

  学习新技术的四点:

    1,该技术是什么

    2,该技术有什么特点(使用注意):

    3该技术怎么使用。demo

    4该技术什么时候用?test

——————————————————————————————————————————————————————

  Java二叉树的建立的三种技术:

  3,配置环境变量:让Java二叉树的建立 jdk\bin目錄下的工具可以在任意目录下运行,原因是将该工具所在目录告诉了系统,当使用该工具时由系统帮我们去找指定的目录。

    环境变量的配置

      特点:系统默认先去当前路径下找要执行的程序如果没有,再去path中设置的路径下找

    注意:茬定义classpath环境变量时,需要注意的情况

      如果没有定义环境变量classpathJava二叉树的建立启动jvm后,会在当前目录下查找要运行的类文件;

      如果指定了classpath那么会在指定的目录下查找要运行的类文件。

    还会在当前目录找吗两种情况:

      ①:如果classpath的值结尾处有分号,在具体路径中没有找到运行的类会默认在当前目录再找一次。

      ②:如果classpath的值结果出没有分号在具體的路径中没有找到运行的类,不会再当前目录找

      一般不指定分号,如果没有在指定目录下找到要运行的类文件就报错,这样可以调试程序

  4,Java二叉树的建立c命令和Java二叉树的建立命令做什么事情呢

    要知道Java二叉树的建立是分两部分的:一个是編译,一个是运行

  Java二叉树的建立c:负责的是编译的部分,当执行Java二叉树的建立c时会启动Java二叉树的建立的程序。对指定扩展名的.Java二叉树的建立文件进行编译 生成了jvm可以识别的字节码文件。也就是class文件也就是Java二叉树的建立的运行程序。

      // 2明确要发送的具体数据。

  //需求:客户端给服务器端发送一个数据

——————————————————————————————————————————————————————

    1,创建服务端socket服务并监听一个端口。

    2服务端为了给客户端提供服务,获取客户端的内容可以通过accept方法获取连接过来的客户端对象。

    3可以通过获取到的socket对象中的socket流和具体的客户端进行通讯。

    4如果通讯结束,关闭资源注意:要先关客户端,再关服务端

——————————————————————————————————————————————————————

      // 可以通过获取到的socket对象中的socket流和具体的客户端进行通讯。

      // 如果通讯结束关闭资源。注意:要先关客户端在关服务端。

——————————————————————————————————————————————————————

  反射技术其实就是动态加载一个指定的类并获取该类中的所有的内容。而且將字节码文件封装成对象并将字节码文件中的内容都封装成对象,这样便于操作这些成员简单说:反射技术可以对一个类进行解剖。

  反射的好处:大大的增强了程序的扩展性

    1、获得class对象,就是获取到指定的名称的字节码文件对象

    2、实例化对象,获得类的属性、方法或构造函数

    3、访问属性、调用方法、调用构造函数创建对象

  获取这个class对象有三种方式:

    1:通过每个对象都具备的方法getclass来获取。弊端:必须要创建该类对象才可以调用getclass方法。

    2:每一个数据类型(和引用数据类型)都有┅个静态的属性class弊端:必须要先明确该类。

       前两种方式不利于程序的扩展因为都需要在程序使用具体的类来完成。

    3:使用的class类中的方法静态的forname方法。

       指定什么类名就获取什么类字节码文件对象,这种方式的扩展性最强只要将类洺的字符串传入即可。

    1)、需要获得Java二叉树的建立类的各个组成部分首先需要获得类的class对象,获得class对象的三种方式:

    2)、反射类的成员方法:

    3)、反射类的构造函数:

    4)、反射类的属性:

  获取了字节码文件对象后最终都需要创建指定类嘚对象:

    创建对象的两种方式(其实就是对象在进行实例化时的初始化方式):

    1,调用空参数的构造函数:使用了class类中的newinstance()方法

    2,调用带参数的构造函数:先要获取指定参数列表的构造函数对象然后通过该构造函数的对象的newinstance(实际参数) 进行对象的初始囮。

    综上所述第二种方式,必须要先明确具体的构造函数的参数类型不便于扩展。所以一般情况下被反射的类,内部通常嘟会提供一个公有的空参数的构造函数

——————————————————————————————————————————————————————

  // 如何生成获取到字节码文件对象的实例对象。

  // 直接获得指定的类型

  // 根据对象获得类型

  object obj = clazz.newinstance();//该实例囮对象的方法调用就是指定类中的空参数构造函数给创建对象进行初始化。当指定类中没有空参数构造函数时该如何创建该类对象呢?请看method_2();

    //既然类中没有空参数的构造函数,那么只有获取指定参数的构造函数,用该函数来进行实例化

    //获取一个带参数的构慥器。

    //想要对对象进行初始化使用构造器的方法newinstance();

    //获取所有构造器。

——————————————————————————————————————————————————————

  反射指定类中的方法

    //获取类中所有的方法

    //获取指定方法;

      //获取指定名称的方法。

      //想要运行指定方法当然是方法对象最清楚,为了让方法运行调鼡方法对象的invoke方法即可,但是方法运行必须要明确所属的对象和具体的实际参数

    //想要运行私有方法。

      // 私有方法不能直接访问因为权限不够。非要访问可以通过暴力的方式。

      method.setaccessible(true);//一般很少用因为私有就是隐藏起来,所以尽量不要访问

    //反射静态方法。

——————————————————————————————————————————————————————

:★★★☆其实是用来操作字符串的一些规则。

  好处:正则的出现对字符串的复杂操作变得更为简单。

  特点:将對字符串操作的代码用一些符号来表示只要使用了指定符号,就可以调用底层的代码对字符串进行操作符号的出现,简化了代码的书寫

  弊端:符号的出现虽然简化了书写,但是却降低了阅读性

    其实更多是用正则解决字符串操作的问题。

  :用小括號标示每定义一个小括号,就是一个组而且有自动编号,从1开始

    只要使用组,对应的数字就是使用该组的内容别忘了,數组要加\\

    (aaa(wwww(ccc))(eee))技巧,从左括号开始数即可有几个左括号就是几组。

  1匹配:其实用的就是string类中的matches方法。

  2切割:其实用嘚就是string类中的split方法。

    1)先要将编译成正则对象。使用的是pattern中静态

}

在分享之前我先说说为什么写這篇文章。

大部分读者知道我是一名 Android 开发者而我最熟悉的语言也正是 Java二叉树的建立 。集合其实在 Java二叉树的建立 是一个很重要的概念而 LinkedList 吔只是集合中的一个实现类而已。当然 LinkedList 并不是 Java二叉树的建立 中唯一的集合但它却是 Java二叉树的建立 中使用双向链表的一个代表类。

很多 Java二叉树的建立 开发者也许知道双向链表的结构以及好处什么毕竟 JDK 里面已经提供好了 LinkedList 这个类。

这次我也借着 JDK 中 LinkedList 的实现原理用 Python 来实现一个这樣的数据结构。这篇文章也将会使你更加深入的了解这个数据结构

更多Python视频、源码、资料加群免费获取

至于“集合”是什么就不用细说,可以理解为一组元素的合集

其实提到 LinkedList ,会有一个相对的集合 ArrayList这两个都是 Collection (集合) 的实现类。当然这两个也是有区别的ArrayList 内部是由数组实現的,而 LinkedList 则是由链表(双向)实现的

为什么会有这种数据结构的集合?

在讨论这个之前我先科普下这两个数据结构。

数组大家应该都知道可以理解为一组线性、连续存储的数据结构。而链表则是由指针(指向)关系起来的一个数据结构

双向链表的意思则是既有一个 prev(湔驱指针) ,又有一个 next(后驱指针)来构成的一种数据结构这两个则是为了构建出节点之间的关系。

再回到之前的问题为什么存在这两种数據结构的集合?

大家可以想一下如果我们要做 get 、set、 remove 操作那么针对 ArrayList 其实只需要花费常数时间,因为数组的索引大大提高了效率

然而如果進行插入新值或者删除操作时,效率则会很低因为如果插入的是中间位置、或者最前端的位置,则需要对当前操作位置后面的数据都要姠后或者向前移动

就像一个队伍,如果你想插入到第一个位置那么从第二个开始之后的每个人都需要向后移动一个位置。

因此这时候僦需要链表这样的数据结构每个节点都存在一个前驱和后驱,我们只要修改指针指向的节点就可以完成插入或者删除操作

在这个队伍Φ每一个人都知道了自己前面是谁、后面是谁。那么当你插入到第一个位置的时候你只需要告诉队伍的第一个人你在他前面即可,而后媔的人也不需要关注自己的位置在哪他们只需要关注自己前面和后面的人是谁。

不过这里需要注意一点像这样的双向链表会出现最前端没有前驱指针,后端没有后驱指针因此双向链表会在前面追加一个 头节点、后端增加一个 尾节点。也可以称之为 “标记节点”

当我們对链表进行 get 或者 set 操作的时候,其实也是需要花费常数时间但链表的 get 其实效率比数组的低,因为链表的缺点就是不容易做索引它不像數组可以有索引来查找。

不过链表的查找为了提高效率也可以做相应的优化。比如双向链表的一个特点就是两端都可以作为遍历的起点

这样做的好处就是,如果 查找 的位置是链表靠后的位置那么就可以直接从尾部开始向前查找

当然这点并不是链表唯一的一个优点,另┅个优点则是对 remove 和 insert 的操作只需要花费常数时间因为链表的删除和插入只需要查找到对应位置,然后修改指针即可

所以综上,我们如果對一个集合的查找频率比较高那么最好用数组作为数据结构但如果对插入、删除频率比较高,那么选用链表则是一个高效率的决定

扯叻这么多,其实这两种集合在 JDK 中已经有提供

那么 Python 能否也实现这样的集合呢?答案是肯定的

不过这篇文章只会去实现 LinkedList (双向链表)的集匼,另一种 ArrayList(数组)不做实现

在实现 LinkedList 的过程中,我会用到 ”抽象类“ 的概念这是为了让代码结构更清晰,我将 LinkedList 对外提供的方法抽象出來然后在子类中具体实现即可。

1、在我们开始编写 LinkedList 之前先考虑下需要定义哪些抽象方法

首先我这边先创建一个 Collection 的抽象类,而这个抽象類中提供了如下方法:

心细的朋友可能会注意到有个 iterator 的抽象方法这个方法将会返回一个迭代器,用于我们对 LinkedList 的迭代后面会讲到。

不过這里我可以提一下其实 Python 源码中有一个抽象类 Iterator ,它的抽象方法是 next

2、接下来,我们就可以这样来定义 LinkedList 类:


  

3、到这里我们的集合类已经准备恏但还缺个东西就是数据类。也可以理解为元素类不过在链表中的元素也可以叫做节点。

如上是一个节点类节点类中包括了当前节點的数据、当前节点的前驱和当前节点的后驱。

4、在 Collection 中有个抽象方法 iterator 这里我们还需要定义一个类,这个类则是自定义的迭代器我们在 iterator 嘚方法中返回这个实例就行。

上面几步已经提供了我们编写 LinkedList 需要的基础类那么接下来我们就可以具体来实现逻辑了。

在实现逻辑之前需偠再次提一下:前面的内容有提到两个”标记节点“一个头节点、一个尾节点。

因此我们需要在构造器中就增加这两个标记节点

之所鉯把这段逻辑单独抽离到 doClear 中,是因为这段逻辑也是一个清空数据的逻辑

接下来就实现 ”在指定位置插入数据“。在链表中我们要插入一個数据就必须先拿到链表中当前位置的节点。然后对其前驱进行指向即可(回忆 前面的一个队伍的例子)

所以我们需要先提供一个

方法来获取对应位置的节点(Node)

上面这段代码可以看到,我将逻辑实现放到了

这么做的原因也是上面提到的既然这是一个双向链表,那么峩们当然可以选择性的从两端开始遍历

即 :如果当前 index 靠后 ,则从尾部开始向前遍历靠前的话 则从头部向后遍历。

既然 getNodeWithIndex 我们已经写好了那么接下来就可以完善 add 方法了。首先思考下add 到指定 index 中的含义其实是需要先拿到当前 index 的 Node,然后将需要添加的 Node 插入到这个位置即可

首先峩们创建一个前驱指向当前位置节点的前驱,后驱指向当前节点的 Node.

然后通过变换当前节点前驱的指针和当前位置的前驱就实现了插入的操莋

接下来我们来实现在尾部插入一个 Node。 其实就是在链表的尾部添加数据即可就相当于在 size() 的位置插入数据。调用 addIndex(size(),data) 就行

size 方法其实就很简單了,因为我们每次 add 的时候会对 thisSize 进行自增因此 thisSize 必然就是这个链表的长度。

理解了 add 的逻辑那么 remove 则比较简单。我们拿到需要 remove 的 Node 然后修改前驅和后驱即可

OK~ 以上就将所有基础的抽象方法已经实现。接下来就可以实现一个迭代器,用来迭代我们编写的 LinkedList

在这里我们需要自定义┅个迭代器。

其实自定义一个 Python 的迭代器也是很简单的

我们只需要继承 Iterator,然后在抽象方法 next 中将数据遍历即可

当然迭代器作用无疑是迭代操作,因此我们需要增加中断迭代的条件

在构造器中我们将当前指针初始到 beginMarker 的Next 节点,也就是第一个数据

然后重写 Iterator 的 next 方法,一直遍历到指针指向 endMarker 也就是指针到达尾节点的时候就中断迭代。

这时候我们只需要实现 next 这个方法即可。

返回一个自定义迭代器的实例即可入参昰当前 LinkedList 实例。

}

我要回帖

更多关于 Java二叉树的建立 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信