数据结构

Java集合框架的基本接口/类层次结构:

java.util.Collection [ I ]

         java.util.List [ I ]

                   java.util.ArrayList [ C ]

                   java.util.LinkedList [ C ]

                   java.util.Vector [ C ]          //线程安全

                            java.util.Stack [ C ]   //线程安全

         java.util.Set [ I ]

                   java.util.HashSet [ C ]

                   java.util.SortedSet [ I ]

                            java.util.TreeSet [ C ]

         java.util.Queue [ I ]

                   java.util.Deque [ I ]

                   java.util.PriorityQueue [C ]

 

java.util.Map [ I ]

         java.util.SortedMap [ I ]

                   java.util.TreeMap [ C ]

         java.util.Hashtable [ C ]            //线程安全

         java.util.HashMap [ C ]

         java.util.LinkedHashMap [ C ]

         java.util.WeekHashMap [ C ]

 

数组

数组是相同数据类型的元素按一定顺序排列的集合,是一块连续的内存空间。数组的优点是:get和set操作时间上都是O(1)的;缺点是:add和remove操作时间上都是O(N)的。

 

链表

链表是一种非连续、非顺序的结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的,链表由一系列结点组成。链表的优点是:add和remove操作时间上都是O(1)的;缺点是:get和set操作时间上都是O(N)的,而且需要额外的空间存储指向其他数据地址的项。查找操作对于未排序的数组和链表时间上都是O(N)。

 

 

队列

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端进行删除操作,而在表的后端进行插入操作,亦即所谓的先进先出(FIFO)。

Java中,LinkedList实现了Deque,可以做为双向队列(自然也可以用作单向队列)。另外PriorityQueue实现了带优先级的队列,亦即队列的每一个元素都有优先级,且元素按照优先级排序。

Deque<Integer> integerDeque = new LinkedList<>();

// 尾部入队,区别在于如果失败了

// add方法会抛出一个IllegalStateException异常,而offer方法返回false

integerDeque.offer(122);

integerDeque.add(122);

// 头部出队,区别在于如果失败了

// remove方法抛出一个NoSuchElementException异常,而poll方法返回false

int head = integerDeque.poll();//返回第一个元素,并在队列中删除

head = integerDeque.remove();//返回第一个元素,并在队列中删除

// 头部出队,区别在于如果失败了

// element方法抛出一个NoSuchElementException异常,而peek方法返回null。

head = integerDeque.peek();//返回第一个元素,不删除

head = integerDeque.element();//返回第一个元素,不删除

 

栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。它体现了后进先出(LIFO)
的特点。

Java中,Stack实现了这种特性,但是Stack也继承了Vector,所以具有线程安全线和效率低下两个特性,最新的JDK8中,推荐用Deque来实现栈,比如:

Deque<Integer> stack = new ArrayDeque<Integer>();

stack.push(12);//尾部入栈

stack.push(16);//尾部入栈

int tail = stack.pop();//尾部出栈,并删除该元素

tail = stack.peek();//尾部出栈,不删除该元素

 

集合

集合是指具有某种特定性质的具体的或抽象的对象汇总成的集体,这些对象称为该集合的元素,其主要特性是元素不可重复。

在Java中,HashSet 体现了这种数据结构,而HashSet是在HashMap的基础上构建的。LinkedHashSet继承了HashSet,使用HashCode确定在集合中的位置,使用链表的方式确定位置,所以有顺序。TreeSet实现了SortedSet 接口,是排好序的集合(在TreeMap 基础之上构建),因此查找操作比普通的Hashset要快(log(N));插入操作要慢(log(N)),因为要维护有序。

 

散列表(哈希表)

散列表也叫哈希表,是根据关键键值(Keyvalue)进行访问的数据结构,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度,这个映射函数叫做散列函数。

Java中HashMap实现了散列表,而Hashtable比它多了一个线程安全性,但是由于使用了全局锁导致其性能较低,所以现在一般用ConcurrentHashMap来实现线程安全的HashMap(类似的,以上的数据结构在最新的java.util.concurrent的包中几乎都有对应的高性能的线程安全的类)。TreeMap实现SortMap接口,能够把它保存的记录按照键排序。LinkedHashMap保留了元素插入的顺序。WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收,而不需要我们手动删除。

 

(二叉树、满二叉树、完全二叉树、二叉查找树、平衡二叉树、堆(堆是一棵完全二叉树))

树(tree)是包含n(n>0)个节点的有穷集合,其中:

  • 每个元素称为节点(node);
  • 有一个特定的节点被称为根节点或树根(root)。
  • 除根节点之外的其余数据元素被分为m(m≥0)个互不相交的结合T1,T2,……Tm-1,其中每一个集合Ti(1<=i<=m)本身也是一棵树,被称作原树的子树(subtree)。

树这种数据结构在计算机世界中有广泛的应用,比如操作系统中用到了红黑树,数据库用到了B+,编译器中的语法树,内存管理用到了堆(本质上也是树),信息论中的哈夫曼编码等等等等,在Java中TreeSet和TreeMap用到了树来排序(二分查找提高检索速度),不过一般都需要程序员自己去定义一个树的类,并实现相关性质,而没有现成的API。下面就用Java来实现各种常见的树。

二叉树:是一种基础而且重要的数据结构,其每个结点至多只有二棵子树,二叉树有左右子树之分,第i层至多有2^(i-1)个结点(i从1开始);深度为k的二叉树至多有2^(k)-1)个结点,对任何一棵二叉树,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1。

 

满二叉树:除最后一层无任何子节点外,每一层上的所有结点都有两个子结点;

完全二叉树:若设二叉树的深度为h,除第 h 层外,其它各层 (1~(h-1)层) 的结点数都达到最大个数,第h层所有的结点都连续集中在最左边,这就是完全二叉树;

满二叉树是完全二叉树的一个特例。

平衡二叉树又被称为AVL树,具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。它的出现就是解决二叉查找树不平衡导致查找效率退化为线性的问题,因为在删除和插入之时会维护树的平衡,使得查找时间保持在O(logn),比二叉查找树更稳定。

 

是一颗完全二叉树,在这棵树中,所有父节点都满足大于等于其子节点的堆叫大根堆,所有父节点都满足小于等于其子节点的堆叫小根堆。堆虽然是一颗树,但是通常存放在一个数组中,父节点和孩子节点的父子关系通过数组下标来确定。

posted @ 2018-08-22 15:27  小驳客  阅读(96)  评论(0)    收藏  举报