数据结构--图 的JAVA实现(下)

在上一篇文章中记录了如何实现图的邻接表。本文借助上一篇文章实现的邻接表来表示一个有向无环图。1,概述图的实现与邻接表的实现最大的不同就是,图的实现需要定义一个数据结构来存储所有的顶点以及能够对图进行什么操作,而邻接表的实现重点关注的图中顶点的实现,即怎么定义JAVA类来表示顶点,以及能够对顶点进行什么操作。为了存储图中所有的顶点,定义了一个Map<key,value>,实际实现为LinkedHashMap<T,VertexInterface<T>>,key为顶点的标识,key是泛型,这样就可以用任意数据类型来标识顶点了,如String、Integer……value当然就是表示顶点的类了,因为我们需要存储的是顶点嘛。即value为VertexInterface<T>。这里为什么不用List而用Map来存储顶点呢?用Map的好处就是方便查询顶点,即可以用顶点标识来查找顶点。这也是为了方便后面实现图的DFS、BFS等算法而考虑的。此外,还定义了一个整型变量edgeCount用来保存图中边的数目,这也是必要的。讨论一个...
代码星球 代码星球·2020-04-04

数据结构--图 的JAVA实现(上)

1,摘要:本系列文章主要学习如何使用JAVA语言以邻接表的方式实现数据结构---图(Graph),这是第一篇文章,学习如何用JAVA来表示图的顶点。从数据的表示方法来说,有二种表示图的方式:一种是邻接矩阵,其实是一个二维数组;一种是邻接表,其实是一个顶点表,每个顶点又拥有一个边列表。下图是图的邻接表表示。从图中可以看出,图的实现需要能够表示顶点表,能够表示边表。邻接表指是的哪部分呢?每个顶点都有一个邻接表,一个指定顶点的邻接表中,起始顶点表示边的起点,其他顶点表示边的终点。这样,就可以用邻接表来实现边的表示了。如顶点V0的邻接表如下:与V0关联的边有三条,因为V0的邻接表中有三个顶点(不考虑V0)。  2,具体分析先来分析边表:在图中如何来表示一条边?很简单,就是:起始顶点指向结束顶点、就是顶点对<startVertex,endVertex>。在这里,为了考虑边带有权值的情况,单独设计一个类Edge.java,作为Vertex.java的内部类,Edge.java如下:1protectedclassEdgeimplementsjava.io.Seria...
代码星球 代码星球·2020-04-04

Storm Topology 提交 总结---Kettle On Storm 实现

一,目的在学习的过程中,需要用到PDI---一个开源的ETL软件。主要是用它来设计一些转换流程来处理数据。但是,在PDI中设计好的transformation是在本地的执行引擎中执行的,(参考源码中的Trans.java),现可以对DI加以改造:在DI中设计的转换,将之转换成Storm的Topology,然后再把该Topology提交到Storm集群中执行。这样,既可以利用DI强大的设计能力(因为在DI中可以设计各种各样的转换流程,这些用DI设计出来的transformation流程是前人已经实现好的数据处理功能,把该transformation转换成StormTopology可以避免自己编写实现数据处理功能的StormTopology代码);又可以利用Storm的分布式实时流处理数据的能力。在PentahoLab官网上有一个相应的开源项目,但是貌似已经不再更新了。参考:kettle-storm的github以及相关介绍 二,实现概述①Storm端的运行流程: 不管在DI中设计了何种转换,将转换转化成Storm的Topology时,都只得到两种类型的Topology...

一致性哈希算法学习及JAVA代码实现分析

1,对于待存储的海量数据,如何将它们分配到各个机器中去?---数据分片与路由当数据量很大时,通过改善单机硬件资源的纵向扩充方式来存储数据变得越来越不适用,而通过增加机器数目来获得水平横向扩展的方式则越来越流行。因此,就有个问题,如何将这些海量的数据分配到各个机器中?数据分布到各个机器存储之后,又如何进行查找?这里主要记录一致性Hash算法如何将数据分配到各个机器中去。 2,衡量一致性哈希算法好处的四个标准:①平衡性:平衡性是指哈希的结果能够尽可能分布到所有的缓冲中去,这样可以使得所有的缓冲空间都得到利用。②单调性:单调性是指如果已经有一些数据通过哈希分配到了相应的机器上,又有新的机器加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到原有的或者新的机器中去,而不会被映射到旧的机器集合中的其他机器上。这里再解释一下:就是原有的数据要么还是呆在它所在的机器上不动,要么被迁移到新的机器上,而不会迁移到旧的其他机器上。③分散性:④负载:参考这里 3,一致性哈希的原理:由于一般的哈希函数返回一个int(32bit)型的hashCode。因此,可以将该哈希函数能够返回...

AVL树的JAVA实现及AVL树的旋转算法

1,AVL树又称平衡二叉树,它首先是一颗二叉查找树,但在二叉查找树中,某个结点的左右子树高度之差的绝对值可能会超过1,称之为不平衡。而在平衡二叉树中,任何结点的左右子树高度之差的绝对值会小于等于1。2,为什么需要AVL树呢?在二叉查找树中最坏情况下查找某个元素的时间复杂度为O(n),而AVL树能保证查找操作的时间复杂度总为O(logn)。   对于一棵BST树而言,不仅有查找操作,也有插入、删除等改变树的形态的操作。随着不断地插入、删除,BST树有可能会退化成链表的形式,使得查找的时间复杂度变成O(N),这种情形下,BST树的结构非常不平衡了。为了保持树的平衡,需要对树的形态做一些限制,因此,引入了AVL树,以保证树的左右子树高度之差的绝对值小于等于1。3,AVL树的JAVA代码实现: AVLTree 继承BinarySearchTree并改写添加节点的add方法,在add方法中判断插入元素后是否导致树不平衡,当不平衡时需要通过旋转进行调整。何时进行旋转调整是通过左右子树的高度之差进行判断的。这里通过rebalance方法使得某结点保持...

数据结构--堆的实现(上)

1,堆是什么?堆的逻辑结构是一颗完全二叉树,但物理结构是顺序表(一维数组)。同时,此处的堆不要与JAVA内存分配中的堆内存混淆。这里讨论的是数据结构中的堆。参考:计算机中的堆是什么?2,数组实现堆的优势及特点由于堆从逻辑上看是一颗完全二叉树,因此可以按照层序遍历的顺序将元素放入一维数组中。注意为了方便,数组的元素存放从索引1处开始(不是0)。采用数组来存放就很容易地找到某个结点i的双亲结点(i/2),孩子结点(左孩子:2i,右孩子:2i+1)3,基于数组的堆的实现需要哪些结构?privateT[]heap;//用来存储堆元素的数组privateintlastIndex;//最后一个元素的索引privatestaticfinalintDEFAULT_INITIAL_CAPACITY=25;首先需要一个一维数组heap来保存堆中的元素;其次,需要lastIndex标记堆中最后一个元素的索引,这样也知道了堆中存放了多少个元素;最后,需要一个final静态变量定义默认构造堆的大小。4,JAVA中基于一维数组的堆的实现具体代码分析①创建堆,假设有N个元素,需要将这N个元素构建大顶堆,有两种方法来...
代码星球 代码星球·2020-04-04

词典的实现(4)-使用Hash方式来实现词典

1,实现思路publicclassHashedDictionary<K,V>implementsDictionaryInterface<K,V>,Serializable{定义HashedDictionary.java,作为Hash词典的实现,该词典实现了如下功能:①向词典中添加元素,②根据查找键从词典中删除元素,③从词典中获取某个查找键的值,④实现了词典中查找键Key的迭代器和Value的迭代器 2,对于Map词典而言,由第一行代码知:它底层实质上是一个数组。第三行代码中的locationUsed用来记录哈希表中某个位置是否被使用。由于冲突处理的需要,当删除某个元素时,只是将该元素作为标记删除而不是真正删除该元素,那么该元素所占用的位置实质上是已经被使用了的。但是,关于这个变量,程序还是有问题的。1privateTableEntry<K,V>[]hashTable;2privateintnumberOfEntries;//hashTable元素个数3privateintlocationUsed;//记录hashTable位置的使用4pri...

词典实现(3)--使用JAVA类库ArrayList实现Map数据结构

1,在词典实现(2)-借助顺序表(数组)实现词典文章中使用了自定义的数组代替ArrayList,并实现了Map数据结构的基本功能。而借助JAVA类库ArrayList类的一些方法可以更加容易地实现Map。 2,实现思路如下ArrayListDictionary.java中定义了一个ArrayList的对象,该ArrayList对象用来存储Entry类的对象,而Entry类封装了(key,value)。这样,利用ArrayList类的一些方法来间接地操作(key,value),从而实现各种词典的操作。 ArrayListDictionary.java中部分代码解释如下: publicArrayListDictionary(){listDictionary=newArrayList<Entry>();}在构造方法中初始化ArrayList对象。这样,每生成一个词典对象,就会有一个ArrayList对象。因为,每个词典对象都需要一个ArrayList对象来存储词典中的元素。 privateclassEntry{Kkey;Vvalue;私有...

词典实现(2)-借助顺序表(数组)实现词典

一,思路1,词典实现类ArrayDictionary.java肯定要implements词典的接口DictionaryInterface.java(参考:http://www.cnblogs.com/hapjin/p/4573826.html)。其次,为了序列化,还要implementsSerializable接口2,由于词典中的每个元素是一个键值对。因此,需要将查找键和值封装在同一个对象中,因而定义了Entry.java来表示词典中的每个元素。其中,Entry类是作为ArrayDictionary的内部类来实现的。3,由于每个Entry对象表示一个词典元素,因此ArrayDictionary.java需要一个Entry类型的数组来存放词典元素。这也是文章的标题--借助顺序表来实现词典的原因。再深入讨论下,我们知道在JAVA类库中ArrayList.java就相当于已经帮程序员实现好了一个顺序表(数组),我们不需要再去关注数组的具体实现细节以及如何遍历数组,而是直接用ArrayList.java中的各种方法(add,remove……)来完成数组的基本操作,通...

词典实现(1)--Map的底层实现

1,词典是这样的一种数据结构:它能根据给定的键(索引值,key)来查找其对应的值(value)是否存在,在JAVA中主要由java.util.HashMap来完成该功能。如电话本就是词典的一个具体实例,其中名字作为键,电话号码作为值。客户端可以通过构造一个电话本来进行查询。本系列文章自己编程实现了Map这一数据结构,模拟实现词典的功能,并给出了词典的两个具体应用---①根据姓名查找电话号码;②统计单词的出现频率2,ADT词典接口DictionaryInterface.java的定义词典接口定义了该词典所具有的基本功能,如添加元素、查询元素……这样,具体的实现类通过implements该接口完成具体的电话本功能的实现。详细解释看代码注释DictionaryInterface.java代码如下:1packagedictionary;23importjava.util.Iterator;45publicinterfaceDictionaryInterface<K,V>{6/*7*Task:将一个新元素插入词典。若给定的键已在词典中,则替换相应的值8*...
代码星球 代码星球·2020-04-04

JAVA单链表的实现-不带头结点但带有尾指针

1,本程序实现了线性表的链式存储结构。实现的链表带有两个指针,一个始终指向链表中的第一个结点,另一个指针始终指向链表中的最后一个结点。之所以设置尾指针,是因为,在插入元素到链表中的末尾时,可以通过尾指针直接找到链表的最后一个元素,从而不需要遍历链表就可以完成插入操作。2,具体实现链表的类名为LList2.java,它首先实现了线性表的接口ListInterface,该接口的定义见:http://www.cnblogs.com/hapjin/p/4549492.htmlLList2.java的代码如下:publicclassLList2<T>implementsListInterface<T>{privateNodefirstNode;//指向第一个结点的指针,该链表是不带头结点的单链表privateNodelastNode;//尾指针,指向链表中的最后一个结点privateintlength;//表示单链表的长度//Node类中不需要定义访问属性的get方法以及set方法,因为Node是内部类,内部类的属性可以直接在外部类中被访问classNode{//Node...

JAVA单链表实现-不带头结点且没有尾指针

本程序采用JAVA语言实现了线性表的链式实现。首先定义了线性表的接口ListInterface,然后LList类实现了ListInterface完成了链表的实现。本实现中,链表是不带表头结点的,且有一个指针始终指向链表中的第一个元素,并没有定义尾指针。因此,每次向链表中插入新结点时需要遍历链表一次。更详细的解释参考《数据结构与算法分析JAVA语言描述第二版》FrankM.Carrano著ListInterface接口的定义如下:publicinterfaceListInterface<T>{publicbooleanadd(TnewEntry);publicbooleanadd(intgivenPosition,TnewEntry);publicvoidclear();publicTremove(intgivenPosition);publicbooleanreplace(intgivenPosition,TnewEntry);publicTgetEntry(intgivenPosition);publicbooleancontains(TanEntry);publicin...

JAVA迭代器学习--在JAVA实现线性表的迭代器

1,迭代器是能够对数据结构如集合(ADT的实现)进行遍历的对象。在遍历过程中,可以查看、修改、添加以及删除元素,这是它与一般的采用循环来遍历集合中的元素不同的地方。因为,通常用循环进行的遍历操作一般是逐个输出元素,而用迭代器不仅仅只是查看元素,还可以改变元素(若迭代器支持remove())。2,在JAVA类库中定义了两个常用的迭代器接口:Iterator和ListIterator,它们为迭代器指定了方法。给某个具体的ADT实现(如,单链表)添加迭代器功能时有以下两种方式:(以链表为例)①将迭代器方法添加到ADT线性表的操作中②将迭代器定义为一个与ADT线性表相互作用的单独的类。②又分两种情况:将该类定义在ADT线性表之外和将该类作为线性表的内部类(具体地说,将该类定义在实现线性表ADT接口的类的内部)3,ADT线性表的display操作(见博文:http://www.cnblogs.com/hapjin/p/4549492.html)执行了一次迭代,但是它仅仅是显示线性表,若还想在遍历的同时对线性表进行其它的操作呢?显然,我们不希望每次需要遍历ADT中的元素时,就构建循环,而是应将线性...

JAVA通过继承线性表来实现有序表

1,对于线性表而言,里面的元素是无序的,可以随意地将新元素增加到线性表中而不需要考虑该元素在线性表中的位置。但是,对于有序表而言,其中的元素是按照某种方式进行排序的,因此在有序表中插入元素时,需要按照顺序将该新元素放置到有序表的合适的位置。但由于有序表与线性表有很多相似的地方,因此,下面通过继承线性表来实现有序表。线性表的实现参考:http://www.cnblogs.com/hapjin/p/4549492.html 2,在Node内部类的实现中,定义了获取Node类的属性的get方法和set方法,这些方法为protected类型的,意味着Node类所在的外部类的子类可以通过这些方法来访问Node类里面的数据域。同样地,在Node类所在的外部类中(LinkedChainBase)也定义了protected类型的方法addFirstNode、getFirstNode、removeFirstNode……这样使得LinkedChainBase的子类可以直接访问其数据域,提高操作的效率。 3,有序表的实现类SortedLinkList.java...

插入排序算法的JAVA实现

1,对元素进行排列时,元素之间需要进行比较,因此需要实现Comparable<T>接口。即,<TextendsComparable<T>>.更进一步,如果允许待比较的类型可以和它的父类型进行比较,则需要写成:<TextendsComparable<?superT>,其中<?superT>表示T的任意超类。2,InsertionSortArray.java类实现了从小到大顺序以插入排序的方式对数据进行排序。3,insertionSort方法负责对每一个元素进行排序,insertInOrder方法将待排序的元素插入到合适的位置,相当于执行具体的操作。具体代码如下:publicclassInsertionSortArray{publicstatic<TextendsComparable<?superT>>voidinsertSort(T[]a,intn){insertionSort(a,0,n-1);//对序列a进行排序,其起始索引为0,最后元素的索引为n-1}//从索引first到last执行插入排序...
首页上一页...570571572573574...下一页尾页