开篇

 

数组

  数组在内存中占据一段连续的内存,所有的数据在内存中连续排列。它的大小是固定的,这一特性使得数组对于插入操作并不友好,分析ArrayList时就会看到这种操作的复杂。但数组对于位置的访问是极其友好的,它支持所谓RandomAccess特性,这使得基于位置的操作可以迅速完成,其时间复杂度为O(1)。数组的数据顺序与插入顺序一致,所以查询操作需要遍历,其时间复杂度为O(n)

  所以数组最大的优势在于基于位置的访问,在扩展性方面表现无力。

链表

  不同于数组,链表是通过指针域来表示数据与数据之间的位置关系的,所以链表在头部或尾部插入数据的复杂度仅为O(1)。链接不具备RandomAccess特性,所以无法提供基于位置的访问。其查询操作也必须从头到尾遍历,复杂度为O(n)

  所以链表最大的优势在于插入,而查询的表现一般。

散列表

  散列表就是Hash Table,结合了数组和链表的优点,这种结构使用key-value形式存储数据,HashMap和HashTable就是基于它。

  数组和链表在查询时表现一般的原因在于他们并不记得数据的位置,所以只能用待查询的数据和存储的数据依次对比。散列表使用一种巧妙的方式来减少甚至避免这种依次对比,它的原理是通过一个函数把任何的key转为int,每次查找时只需要执行这个函数便可以迅速定位。良好的设计使散列表的增、删、查等操作的时间复杂度均为O(1)

二叉排序树

  二叉排序树是解决查询问题的另一方案,如果数据在插入时是有序的,在查询时就可以使用二分法。二分法的时间复杂度为O(lg n)

  树的结构对二分法有天然的支持。二叉排序树牺牲了一部分插入的时间,但提高了查询的速度,同时有序的数据也可以做些其他操作。如果查询的操作重要性超过了插入,就应该考虑这种结构。二叉排序树也存在一些不平衡导致效率下降,所以有了AVL树,红黑树,以及用于数据库索引的B树,B+树等。

原文地址:https://www.cnblogs.com/ryjJava/p/14024156.html