栈和队列是一种逻辑上的数据结构,栈,遵循先进后出的原则,在编译器中得到的应用较多,例如对于括号的匹配(这也是常见的算法题目),表达式的转换等,由于我们只关心栈顶元素,并不需要直接取到栈中间的元素,队列结构类似,只关心首尾元素,十分契合我们链表的特点,
而原本java中是存在stack类的,但现在已经不推荐使用了,一般将Deque这个接口当作栈来使用,它实现的是一个双端队列
作为栈使用的时候一般就用,push(),pop(),peek() 几个方法
队列遵循先进先出的原则,一般用以作任务队列,Queue接口实现方法有:
堆是一棵完全二叉树,最小值总是存在于顶点处,
将这样一棵完全二叉树填入数组中,对于任意一个位置 i ,他的左子节点就在它的2*i 处,右子节点在2*i +1 处,父节点在 i/2 处,所以我们可以用队列来完成一个堆的结构。
当我们用堆进行一个添加操作时:
public boolean add(E e) { return offer(e); // 使用了offer()方法 } public boolean offer(E e) { if (e == null) throw new NullPointerException(); modCount++; int i = size; if (i >= queue.length) grow(i + 1); // 对数组进行扩容 siftUp(i, e); // 将数据插入到合适的位置 size = i + 1; return true; } private void siftUp(int k, E x) { if (comparator != null) siftUpUsingComparator(k, x, queue, comparator); else siftUpComparable(k, x, queue); } private static <T> void siftUpUsingComparator( int k, T x, Object[] es, Comparator<? super T> cmp) { while (k > 0) { int parent = (k - 1) >>> 1; Object e = es[parent]; if (cmp.compare(x, (T) e) >= 0) break; es[k] = e; k = parent; } es[k] = x; } private static <T> void siftUpComparable(int k, T x, Object[] es) { Comparable<? super T> key = (Comparable<? super T>) x; while (k > 0) { int parent = (k - 1) >>> 1; Object e = es[parent]; if (key.compareTo((T) e) >= 0) break; es[k] = e; k = parent; } es[k] = key; }
插入策略是在末尾创建一个空位,然后将这个插入元素与父节点进行比较,满足条件就和父节点交换,直到退出循环;
删除根节点数据策略也类似,每次将左子节点和右子节点的最小数据放到父节点处即可(以小顶堆为例);
原文:https://www.cnblogs.com/xtoshii/p/13681819.html