LinkedList :双向链表在java中的实现
实现了deque、queue 接口
栈
Java中有Stack类,但现在已经过时了,不推荐使用。一个更好的方法是使用Deque接口实现栈(Deque意为双端队列,double ended queue)。具体来说又有ArrayDeuqe和LinkedList两种具体类来实现,两者的区别体现在底层分别使用数组和链表来实现。
常用的重要函数包括:
push(); // 向stack栈顶压入一个元素
pop(); // 从stack中弹出栈顶元素
peek(); // 查看stack中栈顶元素,不弹出
队列
使用Queue接口实现,具体的实现类有LinkedList。
常用的重要函数包括:
向队列尾部添加元素:
offer(); // 如果因为长度不够等原因插入失败,返回false
add(); // 如果插入失败会抛出异常:IllegalStateException;
查看头部元素 ,不改变队列:
peek(); // 如果队列中没有元素,返回null;
element(); // 如果队列中没有元素,则抛出异常:NoSuchElementException;
取出队首元素(返回队首元素,队列中不再包含此元素):
poll(); // 会在没元素时返回null;
remove(); // 会在没元素时抛出异常:NoSuchElementException;
package com;
import java.util.*;
public class test {
public static void main(String[] args) {
String numberStr = "";
// 链表
LinkedList linkedList = new LinkedList();
linkedList.addFirst(1);
linkedList.addFirst(2);
linkedList.addLast(3);
while (!linkedList.isEmpty()) {
numberStr = numberStr + linkedList.pollLast();
}
// 312
System.out.println(numberStr);
// 栈
Deque stack = new LinkedList<>();
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println(" " + stack.peek());
System.out.println(stack.pop());
Iterator iterator = stack.iterator();
while (iterator.hasNext()) {
System.out.printf(iterator.next() + " ");
}
// queue
Queue queue = new LinkedList();
Integer n = 10;
for (int i = 0; i < n; i++)
queue.add(i);
numberStr = "";
while (!queue.isEmpty()) {
numberStr = numberStr + queue.poll();
}
System.out.println(numberStr);
}
}
优先队列
PriorityQueue类实现了优先队列,默认是一个小根堆的形式,如果要定义大根堆,需要在初始化的时候加入一个自定义的比较器。
PriorityQueueSortTest
package data.structure;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Random;
/**
* PriorityQueue
* 默认实现小根堆有序
* 自定义实现大根堆有序
*/
@SuppressWarnings("Since15")
public class PriorityQueueSortTest {
static Random random = new Random();
public static void main(String[] args) {
PriorityQueue priorityQueue = new PriorityQueue();
for (int i = 0; i < 10; i++) {
Integer next = random.nextInt(100);
priorityQueue.offer(next);
}
PriorityQueue minHeap = new PriorityQueue(5);
//堆有序之 - 默认实现小根堆有序
minHeap.addAll(priorityQueue);
PriorityQueue maxHeap = new PriorityQueue();
maxHeap.addAll(priorityQueue);
// 实现大根堆有序
maxHeap = maxHeap(maxHeap);
// 结果打印到控制台
// 小根堆
ergodic(minHeap);
// 大根堆
ergodic(maxHeap);
// 归并+交换排序
Arrays.sort(new Integer[]{1, 2, 5, 4}, new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
}
/**
* 遍历输出
*/
public static void ergodic(PriorityQueue priorityQueue) {
while (!priorityQueue.isEmpty()) {
System.out.println(priorityQueue.poll());
}
System.out.println("--------------");
}
/**
* 堆有序之-大根堆
*/
public static PriorityQueue maxHeap(PriorityQueue priorityQueue) {
// 动态扩容的,5作用不大
PriorityQueue priorityQueueMax = new PriorityQueue(5, new MaxHeapComparator());
priorityQueueMax.addAll(priorityQueue);
return priorityQueueMax;
}
/**
* 自定义比较器
*/
public static final class MaxHeapComparator implements Comparator<Integer> {
/**
* @param newElement 新来的元素
* @param queueElement 队列中当前最大元素
* @return 返回一个负整数、零或正整数作为第一个参数小于、等于或大于第二参数
* 如果新来的元素大于 当前队列中最后一个元素,即 comparator.compare(x, (E) e) 返回负数,优先队列将该元素上浮,如果比素组中所有元素都大,
* 则一直上浮为堆顶( 数组下标为1,第一个出队的元素),优先级最高。
* 如果第一个元素小于第二个元素,则返回负数,表示
*/
public int compare(Integer newElement, Integer queueElement) {
return queueElement.compareTo(newElement);
}
/* 优先队列比较元素时的源码
private void siftUpUsingComparator(int k, E x) {
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = queue[parent];
if (comparator.compare(x, (E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = x;
}
*/
}
}
PriorityQueueTopNTest
package data.structure;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;
/**
* topN 问题
* java 优先队列 实现了堆的接口
* 1.求一组无序数中的前5个最小的数
* 1.求一组无序数中的前5个最大的数
*/
@SuppressWarnings("Since15")
public class PriorityQueueTopNTest {
/**
* 第前N个
*/
private static final Integer N = 5;
public static void main(String[] args) {
// 给定一个10个元素的无序数组
Integer[] list = {1, 100, 20, 30, 15, 26, 10, 20, 5, 87};
// 找出最小的前5个元素
PriorityQueue topMinN = topMinN(list, N);
// 找出最大的前5个元素
// Integer n = 5;
PriorityQueue topMaxN = topMaxN(list, N);
// 输出到控制台
while (!topMinN.isEmpty()) {
System.out.println(topMinN.poll());
}
System.out.println("------------");
while (!topMaxN.isEmpty()) {
System.out.println(topMaxN.poll());
}
}
/**
* 找出最大的前N个元素
*
* @param list 无序数组
* @param n N
* @return PriorityQueue
*/
public static PriorityQueue topMaxN(Integer[] list, Integer n) {
// 取前5个元素初始化一个5个元素的小根堆(最小的元素在堆顶)
PriorityQueue priorityQueue = new PriorityQueue();
for (int i = 0; i < n; i++) {
priorityQueue.offer(list[i]);
}
// 如果新来元素比堆顶元素还小,直接丢弃,否则堆顶元素出队,将新元素加入堆(优先队列),并实现自动上浮
for (int i = n; i < list.length; i++) {
if (list[i].compareTo((Integer) priorityQueue.peek()) < 0) {
continue;
} else {
priorityQueue.poll();
priorityQueue.offer(list[i]);
}
}
return priorityQueue;
}
/**
* 找出最小的前N个元素
*
* @param list 无序数组
* @param n N
* @return PriorityQueue
*/
private static PriorityQueue topMinN(Integer[] list, Integer n) {
// 取前5个元素初始化一个5个元素的大根堆(最大的元素在堆顶)
PriorityQueue priorityQueue = new PriorityQueue(new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
for (int i = 0; i < n; i++) {
priorityQueue.offer(list[i]);
}
// 如果新来元素比堆顶元素还大,直接丢弃,否则堆顶元素出队,将新元素加入堆(优先队列),并实现自动上浮
for (int i = n; i < list.length; i++) {
if (list[i].compareTo((Integer) priorityQueue.peek()) > 0) {
continue;
} else {
priorityQueue.poll();
priorityQueue.offer(list[i]);
}
}
return priorityQueue;
}
}
使用场景
优先队列的topN 用于快速从大数据中获取最值元素