其实这个问题的完整描述就是:PriorityQueue在Java中的实现,其数据的逻辑结构是线性结构吗?它的数据的物理结构是什么?估计很多人的回答是:PriorityQueue是一个线性结构,因为PriorityQueue是优先队列的实现。队列不是线性结构吗?但是在PriorityQueue的实现中,其数据的逻辑结构是树形结构,物理结构是顺序存储结构。要理解这个问题,首先要理解什么是数据的逻辑结构,什么是数据的物理结构。顾名思义,数据的逻辑结构是指数据如何组织,数据的物理结构是指数据如何存储。数据的逻辑结构和物理结构是数据结构中非常重要的两个要素。但是你知道数据有几种逻辑结构和几种物理结构吗?数据的逻辑结构数据的逻辑结构是指数据如何组织,反映数据元素之间的逻辑关系,更贴近实际。比如在现实生活中,树干和树叶是树结构,队列是线性关系。数据的逻辑结构一般有四种,即:线性结构、集合结构、树结构和网络结构。其中,我们将集合、树结构、网络结构统称为非线性结构。线性结构线性结构是指数据结构中元素之间的一对一关系。例如:数组是一个线性结构,其下标与元素一一对应。链表也是一种线性结构,它的元素是一个接一个的。生活中有很多类似的例子。比如买票的队列就是一个线性结构。超市里整齐排列的商品也是线性结构。逻辑结构的线性结构集合结构集合结构是指元素之间除了“属于同一个集合”的关系外,没有其他关系。比如数学中的整数是一个集合,所有的小数也是一个集合。集合逻辑结构的树状结构树状结构是指元素之间存在一对多的关系。比如水果有香蕉、草莓、西瓜等,这个逻辑结构就是一个树结构。逻辑结构线树结构网络结构网络结构是指元素之间的多对多关系。网络结构也称为网状结构,是一种多对多的关系。例如,在一个城市的交通网络中,每栋房子与其他房子之间有很多条道路。逻辑结构线网络结构数据的物理存储结构数据的物理结构是指数据如何存储,反映了数据的存储结构。数据存储结构有四种:顺序存储、链式存储、索引存储和散列存储。通常,我们将这四种物理结构分为顺序存储结构和非顺序存储结构。顺序存储是顺序存储结构,而链接存储、索引存储、哈希存储都是非顺序存储结构。数据的顺序存储结构的特点是数据元素之间的逻辑关系由元素的相对位置来表示。非顺序存储的特点是:数据元素之间的逻辑关系是通过指示元素存储地址的指针来表达的。注意:有朋友说数据的物理存储结构只有顺序存储和链式存储,不存在索引存储和哈希存储。对此,我以后会专门写一篇文章来谈谈这件事。顺序存储顺序存储是指数据按顺序存储在内存中,逻辑结构上相邻的元素在物理结构上也相邻。Java中的ArrayList是顺序存储实现的。物理结构的顺序存储链接存储链接存储是指元素之间的逻辑顺序,不是通过内存顺序分配的,而是通过引用来组织的。也就是说,逻辑上相邻的元素在物理存储位置上并不相邻。Java中的LinkedList是通过链式存储实现的。物理结构的链接存储索引存储索引存储是指元素之间的逻辑关系,通过索引表来存储。这个索引表有很多索引项,每个索引项存储两条信息:关键字和数据存储地址。我们可以通过关键字找到对应的数据存储地址。这就好比一本书的目录,关键字就是章节名,数据存储地址就是页码。我们可以通过章节名快速找到对应的页码,从而快速找到本书对应的内容。物理结构的索引存储哈希存储哈希存储也称为哈希存储,它与索引存储非常相似,通过索引值和对应值实现快速查找。唯一的区别是索引存储散列索引值。应该说哈希存储是索引存储的一种比较复杂的实现。物理结构的哈希存储识别看到这里,我们对数据的逻辑结构和物理结构有了基本的了解,也知道了它们的常见类型。那么我们如何判断它们属于哪一种逻辑结构,属于哪一种物理结构呢?以Java中优先级队列的PriorityQueue实现为例。通过阅读源码我们知道底层是使用二叉堆实现的,而二叉堆本身其实就是一棵二叉树。即对于PriorityQueue来说,它的数组最终是通过下图所示的逻辑结构来组织的,所以PriorityQueue的逻辑结构是一个树形结构。PriorityQueue的逻辑结构从PriorityQueue的源码我们可以知道,PriorityQueue的数据最终是通过一个对象数组存储的,数组的物理结构是顺序存储的。所以对于PriorityQueue来说,它的物理结构是一个顺序存储结构。PriorityQueue的类成员变量通过PriorityQueue的例子,我们可以总结出判断数据的逻辑结构和物理结构的思想:判断逻辑结构取决于数据是如何组织的。判断物理结构,要看数据最终是如何存储的。如果对PriorityQueue的源码实现感兴趣,可以阅读:收藏系列队列(九):PriorityQueue-陈树义的博客下面我们就用这个方法来判断TreeMap类。TreeMap是Java中非常经典的实现。它的底层是基于红黑树的,也就是最终会把所有的数据组织成一颗红黑树。因此,TreeMap的逻辑结构是一个树结构。通过阅读TreeMap的源码我们知道,TreeMap的数据最终是通过Entry类存储的,所以TreeMap的物理结构是一个链式存储结构。TreeMap的类成员变量最后我们来分析一下比较复杂的LinkedBlockingQueue。很多人会说队列是一种特殊的数组,数组是顺序存储的,所以队列也是顺序存储的。如果把这个结论应用到LinkedBlockingQueue上,是不是也能得出同样的结论,即LinkedBlockingQueue也是顺序存储的呢?我们前面说过:不要用直觉去判断,要根据定义去判断。即判断数据的逻辑结构和物理结构的思路是:判断逻辑结构取决于数据是如何组织的。判断物理结构,要看数据最终是如何存储的。LinkedBlockingQueue是Java中的阻塞队列实现,最终将数组组织成队列,因此其逻辑结构属于线性链表。通过阅读源码我们可以知道LinkedBlockingQueue的元素是存储在Node节点上的,所以LinkedBlockingQueue的物理结构属于链式存储。LinkedBlockingQueue类成员变量总结文章开头通过PriorityQueue的例子介绍了逻辑结构和物理结构的话题。接着介绍了四种逻辑结构:线性表、集合、树结构、网络结构。
