数据结构-双向链表、栈、队列、优先队列与堆

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 用于快速从大数据中获取最值元素

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值