数据结构(java)

数据结构

数组

数组是由一组元素(值或变量)组成的数据结构,每个元素有至少一个索引或键来标识

空间占用

Java中数组结构为:

8字节markword

4字节class指针(压缩class指针的情况)

4字节数组大小(决定了数组的最大容量是2^32)

数组元素+对其字节(java中所有对象大小都是8字节的整数倍 , 不足的要用对齐字节补足)

动态数组

Java中自带的动态数组:ArrayList,集合底层其实就是一个动态的、自动扩容的数组。

import java.util.Arrays;
import java.util.Iterator;
import java.util.function.Consumer;
import java.util.stream.IntStream;

public class Array implements Iterable<Integer> {
    private int size = 0;
    private int capacity = 8;
    private int[] array = {};

    //在数组的最后添加一个元素
    public void addLast(int element){
        checkAndGrow();
        array[size] = element;
        size++;
    }

    //向数组的index索引插入element
    public void add(int index , int element){
        checkAndGrow();

        if(index < size && index >=0){
            System.arraycopy(array , index , array , index+1 , size - index);
            array[index] = element;
            size++;
        }
    }

    //获得数组中位于index的元素
    public int get(int index){
        return array[index];
    }

    //遍历
    public void foreach(Consumer<Integer> consumer){
        for(int i = 0;i<size ;i++){
            consumer.accept(array[i]);
        }
    }

    //iterator遍历
    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            int i = 0;

            @Override
            public boolean hasNext() {
                return i<size;
            }

            @Override
            public Integer next() {
                return array[i++];
            }
        };
    }

    //流遍历
    public IntStream stream(){
        return IntStream.of(Arrays.copyOfRange(array , 0 , size));
    }


    //删除
    public int remove(int index){
        int removed = array[index];
        System.arraycopy(array , index +1 , array , index  , size - index);
        size--;
        return removed;
    }

    //检查并扩容
    public void checkAndGrow(){
        if(size == 0){
            array = new int[capacity];
        }
        //扩容
        if(size == capacity){
            capacity += capacity>>1;
            int[] newArray = new int[capacity];
            System.arraycopy(array , 0 , newArray , 0 , size);
            array = newArray;
        }

    }
}

二维数组

在这里插入图片描述

链表

  • 单向链表,每个元素有个指针指向下一个元素
  • 双向链表,每个元素有两个指针分别指向上一个和下一个元素
  • 循环链表,循环链表尾节点指向头节点head

链表内还有一种特殊的节点称为哨兵节点,也叫做哑元节点,它不存储数据,通常用作头尾,用来简化边界判断

import java.util.Iterator;
import java.util.function.Consumer;

public class SinglyLinkedList implements Iterable<Integer>{//整体
    Node head;//头指针

    @Override
    public Iterator<Integer> iterator() {
        return new IntegerIterator();
    }

    private static class Node{
        int value;//值
        Node next;//下一个节点指针

        public Node(int value , Node next){
            this.value = value;
            this.next = next;
        }
    }
    //插入头部
    public void addFirst(int value){
        head = new Node(value , head);
    }
    //遍历
    public void loop(){
        Node p = head;
        while(p!=null){
            System.out.println(p.value);
            p = p.next;
        }
    }
    //遍历
    public void loop2(Consumer<Integer> consumer){
        Node p = head;
        while(p!=null){
            consumer.accept(p.value);
            p = p.next;
        }

    }
    //遍历
    private class IntegerIterator implements Iterator<Integer> {
        Node p = head;

        @Override
        public boolean hasNext() { //是否有下一个元素
            return p!=null;
        }

        @Override
        public Integer next() { //返回当前值,并指向下一个元素
            int v = p.value;
            p = p.next;
            return v;
        }
    }

    //找到最后一个
    private Node findLast(){
        if(head == null){
            return null;
        }

        Node p;
        for(p = head ; p.next != null;p = p.next){

        }
        return p;
    }
    //插入尾部
    public void addLast(int value){
        Node last = findLast();
        if(last == null){
            addFirst(value);
        }
        last.next = new Node(value , null);
    }
    //找到节点
    private Node findNode(int index){
        int i = 0;
        for(Node p = head;p !=null;p = p.next,i++){
            if(i==index){
                return p;
            }
        }
        return null;//没找到
    }
    //得到相应值
    public int get(int index){
        Node node = findNode(index);
        if(node==null){
            throw new IllegalArgumentException(
                    String.format("index [%d] 不合法%n" , index)
            );
        }
        return node.value;
    }
    //插入
    public void insert(int index , int value){
        if(index == 0){
            addFirst(value);
            return ;
        }
        Node prev = findNode(index - 1);//上一个节点
        if(prev == null){//上一个节点为空
                throw new IllegalArgumentException(
                        String.format("index [%d] 不合法%n" , index)
                );
            }
        prev.next = new Node(value , prev.next);
    }
    //移除第一个
    public void removeFirst(){
        if(head == null){
            throw new IllegalArgumentException(
                    String.format("index [%d] 不合法%n" , 0)
            );
        }
        head = head.next;
    }
    //移除
    public void remove(int index){
        if(index == 0){
            removeFirst();
            return;
        }
        Node prev = findNode(index - 1);//上一个节点
        if(prev == null){
            throw new IllegalArgumentException(
                    String.format("index [%d] 不合法%n" , index)
            );
        }
        Node removed = prev.next; // 被删除的节点
        if(removed == null){
            throw new IllegalArgumentException(
                    String.format("index [%d] 不合法%n" , index)
            );
        }
        prev.next = removed.next;
    }


}

单向链表-带哨兵

import java.util.Iterator;
import java.util.function.Consumer;
//带哨兵链表
public class SentryLinkedList implements Iterable<Integer>{//整体
    private Node head = new Node(666 , null);//头指针

    @Override
    public Iterator<Integer> iterator() {
        return new IntegerIterator();
    }

    private static class Node{
        int value;//值
        Node next;//下一个节点指针

        public Node(int value , Node next){
            this.value = value;
            this.next = next;
        }
    }
    //插入头部
    public void addFirst(int value){
        head = new Node(value , head);
    }
    //遍历
    public void loop(){
        Node p = head.next;
        while(p!=null){
            System.out.println(p.value);
            p = p.next;
        }
    }
    //遍历
    public void loop2(Consumer<Integer> consumer){
        Node p = head.next;
        while(p!=null){
            consumer.accept(p.value);
            p = p.next;
        }

    }
    //遍历
    private class IntegerIterator implements Iterator<Integer> {
        Node p = head.next;

        @Override
        public boolean hasNext() { //是否有下一个元素
            return p!=null;
        }

        @Override
        public Integer next() { //返回当前值,并指向下一个元素
            int v = p.value;
            p = p.next;
            return v;
        }
    }

    //找到最后一个节点
    private Node findLast(){
        Node p;
        for(p = head ; p.next != null;p = p.next){

        }
        return p;
    }
    //插入尾部
    public void addLast(int value){
        Node last = findLast();
        last.next = new Node(value , null);
    }
    //找到节点
    private Node findNode(int index){
        int i = 0;
        for(Node p = head.next;p !=null;p = p.next,i++){
            if(i==index){
                return p;
            }
        }
        return null;//没找到
    }
    //得到相应值
    public int get(int index){
        Node node = findNode(index);
        if(node==null){
            throw new IllegalArgumentException(
                    String.format("index [%d] 不合法%n" , index)
            );
        }
        return node.value;
    }
    //插入
    public void insert(int index , int value){
        if(index == 0){
            addFirst(value);
            return;
        }
        Node prev = findNode(index - 1);//上一个节点
        if(prev == null){//上一个节点为空
                throw new IllegalArgumentException(
                        String.format("index [%d] 不合法%n" , index)
                );
            }
        prev.next = new Node(value , prev.next);
    }
    //移除第一个
    public void removeFirst(){
        if(head == null){
            throw new IllegalArgumentException(
                    String.format("index [%d] 不合法%n" , 0)
            );
        }
        head = head.next;
    }
    //移除
    public void remove(int index){
        if(index == 0){
            removeFirst();
            return;
        }
        Node prev = findNode(index - 1);//上一个节点
        if(prev == null){
            throw new IllegalArgumentException(
                    String.format("index [%d] 不合法%n" , index)
            );
        }
        Node removed = prev.next; // 被删除的节点
        if(removed == null){
            throw new IllegalArgumentException(
                    String.format("index [%d] 不合法%n" , index)
            );
        }
        prev.next = removed.next;
    }
}

双向链表-带哨兵

import java.util.Iterator;
import java.util.Spliterator;
import java.util.function.Consumer;

public class DoublyLinkedListSentinel implements Iterable<Integer>{
    static class Node{
        Node prev;//上一个结点指针
        int value;//值
        Node next;//下一个结点指针

        public Node(Node prev , int value , Node next){
            this.prev = prev;
            this.value = value;
            this.next = next;
        }
}
    private Node head;//头哨兵
    private Node tail;//尾哨兵

    public DoublyLinkedListSentinel(){
        head = new Node(null , 666 , null);
        tail = new Node(null , 888 , null);
        head.next = tail;
        tail.prev = head;
    }

    private Node findNode(int index){
        int i = -1;
        for(Node p = head; p != tail ; p = p.next , i++){
            if(i == index){
                return p;
            }
        }
        return null;
    }

    public void insert(int index , int value){
        Node prev = findNode(index - 1);
        if(prev == null){
            throw new IllegalArgumentException(
                    String.valueOf(index)
            );
        }
        Node next = prev.next;
        Node inserted = new Node(prev , value , next);
        prev.next = inserted;
        next.prev = inserted;
    }

    public void addFirst(int value){
        insert(0 , value);
    }

    public void removeFirst(){
        remove(0);
    }

    public void remove(int index){
        Node prev = findNode(index - 1);
        if(prev == null){
            throw new IllegalArgumentException(
                    ""+index
            );
        }
        Node removed = prev.next;
        if(removed == tail){
            throw new IllegalArgumentException(
                    ""+index
            );
        }
        Node next = removed.next;

        prev.next = next;
        next.prev = prev;
    }

    public void addLast(int value){
        Node last = tail.prev;
        Node added = new Node(last , value , tail);
        last.next = added;
        tail.prev = added;
    }

    public void removeLast(){
        Node removed = tail.prev;
        Node prev = removed.prev;
        prev.next = tail;
        tail.prev = prev;
    }


    @Override
    public void forEach(Consumer<? super Integer> action) {
        Iterable.super.forEach(action);
    }

    @Override
    public Spliterator<Integer> spliterator() {
        return Iterable.super.spliterator();
    }

    @Override
    public Iterator<Integer> iterator() {
        return null;
    }
}

环形链表-带哨兵

import java.util.Iterator;

public class DoubleLinkedListCircular implements Iterable<Integer>{

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            Node p = sentinel.next;
            @Override
            public boolean hasNext() {
                return p!=sentinel;
            }

            @Override
            public Integer next() {
                int value = p.value;
                p = p.next;
                return value;
            }
        };
    }

    private static class Node{
        Node prev;
        int value;
        Node next;

        public Node(Node prev , int value , Node next){
            this.prev = prev;
            this.value = value;
            this.next = next;
        }
    }

    private Node sentinel = new Node(null , -1 , null);

    public DoubleLinkedListCircular(){
        sentinel.prev = sentinel;
        sentinel.next = sentinel;
    }

    public void addFirst(int value){
        Node a = sentinel;
        Node b = sentinel.next;
        Node added = new Node(a , value , b);
        a.next = added;
        b.prev = added;
    }

    public void addLast(int value){
        Node b = sentinel;
        Node a = sentinel.prev;
        Node added = new Node(a , value , b);
        a.next = added;
        b.prev = added;
    }

    public void removeFirst(){
        Node removed = sentinel.next;
        if(removed == sentinel){
            throw new IllegalArgumentException(
                    "非法"
            );
        }
        Node a = sentinel;
        Node b = removed.next;

        a.next = b;
        b.prev = a;
    }

    public void removeLast(){
        Node removed = sentinel.prev;
        if(removed == sentinel){
            throw new IllegalArgumentException(
                    "非法"
            );
        }
        Node a = removed.prev;
        Node b = sentinel;
        a.next = b;
        b.prev = a;
    }

    public void removeByValue(int value){
        Node removed = findByValue(value);
        if(removed == null){
            return ;
        }
        Node a = removed.prev;
        Node b = removed.next;
        a.next = b;
        b.prev = a;
    }

    private Node findByValue(int value){
        Node p = sentinel.next;
        while(p != sentinel){
            if(p.value == value){
                return p;
            }
            p = p.next;
        }
        return null;
    }


}

队列

概述

计算机科学中,queue是以顺序的方式维护的一组数据集合,在一端添加数据,从另一端移除数据。习惯来说,添加的一端为尾,移除的一端为头。

import java.util.Iterator;

public class LinkedListQueue<E> implements Queue<E> , Iterable<E> {

    private static class Node<E>{
        E value;
        Node<E> next;

        public Node(E value , Node<E> next){
            this.value = value;
            this.next = next;
        }
    }

    private Node<E> head = new Node<>(null , null);
    private Node<E> tail = head;
    private int size; //节点数
    private int capacity; //容量

    {
        tail.next = head;
    }

    public LinkedListQueue(int capacity){
        this.capacity = capacity;
    }

    public LinkedListQueue(){
    }

    @Override
    public boolean offer(E value) {
        if(isFull()){
            return false;
        }
        Node<E> added = new Node<>(value , head);
        tail.next = added;
        tail = added;
        size++;
        return true;
    }


    @Override
    public E poll() {
        if(isEmpty()){
            return null;
        }
        Node<E> first = head.next;
        head.next = first.next;
        size--;
        return first.value;
    }

    @Override
    public E peek() {
        if(isEmpty()){
            return null;
        }
        return head.next.value;
    }

    @Override
    public boolean isEmpty() {
        return head == tail;
    }

    @Override
    public boolean isFull() {
        return size == capacity;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            Node<E> p = head.next;
            @Override
            public boolean hasNext() {
                return p != head;
            }

            @Override
            public E next() {
                E value = p.value;
                p = p.next;
                return value;
            }
        };
    }


}

计算机科学中,stack是一种线性的数据结构,只能在其一段添加数据和移除数据。习惯来说,这一端称之为栈顶,另一端不能操作数据的称之为栈底,如同生活中的一摞书

import java.util.Iterator;

public class ArrayStack<E> implements Stack<E> , Iterable<E> {

    private E[] array;
    private int top; // 栈顶指针

    @SuppressWarnings("all")
    public ArrayStack(int capacity){
        this.array = (E[]) new Object[capacity];
    }

    @Override
    public boolean push(E value) {
        if(isFull()){
            return false;
        }
        array[top++] = value;
        return true;
    }

    @Override
    public E pop() {
        if(isEmpty()){
            return null;
        }
        E value = array[top - 1];
        top--;
        return value;
    }

    @Override
    public E peek() {
        if(isEmpty()){
            return null;
        }
        return array[top - 1];
    }

    @Override
    public boolean isEmpty() {
        return top == 0;
    }

    @Override
    public boolean isFull() {
        return top == array.length;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            int p = top;
            @Override
            public boolean hasNext() {
                return p>0;
            }

            @Override
            public E next() {
                E value = array[--p];
                return value;
            }
        };
    }
}

双端队列

队列:一端删除(头)一端添加(尾)

栈:一端删除和添加(顶)

双端队列:两端都可以删除、添加

优先级队列:优先级高者先出队

延时队列:根据延时时间确定优先级

并发阻塞队列:队列空或满时不阻塞

并发阻塞队列:队列空时删除阻塞、队列满时添加阻塞

import java.util.Iterator;

public class LinkedListDeque<E> implements Deque<E> , Iterable<E> {
    // a added b
    @Override
    public boolean offerFirst(E e) {
        if(isFull()){
            return false;
        }
        Node<E> a = sentinel;
        Node<E> b = sentinel.next;
        Node<E> added = new Node(a , e , b);
        a.next = added;
        b.prev = added;
        size++;
        return false;
    }

    @Override
    public boolean offerLast(E e) {
        if(isFull()){
            return false;
        }
        Node<E> a = sentinel.prev;
        Node<E> b = sentinel;
        Node<E> added = new Node<>(a , e , b);
        a.next = added;
        b.prev = added;
        size++;
        return true;
    }

    @Override
    public E pollFirst() {
        if(isEmpty()){
            return null;
        }
        Node<E> a = sentinel;
        Node<E> removed = sentinel.next;
        Node<E> b = removed.next;
        a.next = b;
        b.prev = a;
        size --;
        return removed.value;
    }

    @Override
    public E pollLast() {
        if(isEmpty()){
            return null;
        }
        Node<E> b = sentinel;
        Node<E> removed = sentinel.prev;
        Node<E> a = removed.prev;
        a.next = b;
        b.prev = a;
        size--;
        return removed.value;
    }

    @Override
    public E peekFirst() {
        if(isEmpty()){
            return null;
        }
        return sentinel.next.value;
    }

    @Override
    public E peekLast() {
        if(isEmpty()){
            return null;
        }
        return sentinel.prev.value;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public boolean isFull() {
        return size == capacity;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            Node<E> p = sentinel.next;
            @Override
            public boolean hasNext() {
                return p != sentinel;
            }

            @Override
            public E next() {
                E value = p.value;
                p = p.next;
                return value;
            }
        };
    }

    static class Node<E> {
        Node<E> prev;
        E value;
        Node<E> next;

        public Node(Node<E> prev , E value , Node<E> next){
            this.prev = prev;
            this.value = value;
            this.next = next;
        }
    }

    int capacity;
    int size;
    Node<E> sentinel = new Node<>(null , null , null);
    public LinkedListDeque(int capacity){
        this.capacity = capacity;
        sentinel.next = sentinel;
        sentinel.prev = sentinel;
    }
}

二叉树

二分搜索树(Binary Search Tree)

平衡二叉树;AVL;红黑树

堆;并查集

线段树;Trie(字典树,前缀树)

二叉树:

  • 和链表一样,动态数据结构

  • class Node{
    	E e;
    	Node left;
    	Node right;
    }
    
package BST;

import.LinkedListStack;
import.Stack;

import java.util.LinkedList;
import java.util.Queue;

public class BST<E extends Comparable<E>> {
    private class Node{
         E e;
         Node left , right;
        public Node(E e){
            this.e = e;
            left = null;
            right = null;
        }
    }
    private Node root;
    private int size;

    public BST(){
        root = null;
        size = 0;
    }

    public int size(){
        return size;
    }

    public boolean isEmpty(){
        return size == 0;
    }

    public void add(E e){
        if(root == null){
            root = new Node(e);
            size++;
        }else {
            add(root , e);
        }
    }

    //看二分搜索树中是否包含元素e
    public boolean contains(E e){
        return contains(root , e);
    }

    private boolean contains(Node node , E e){
        if(node == null){
            return false;
        }
        if(e.compareTo(node.e) == 0){
            return true;
        }else if(e.compareTo(node.e)<0){
            return contains(node.left , e);
        }else {
            return contains(node.right , e);
        }
    }


    //向以node为根的二分搜索树中插入元素E,递归算法
    private Node add(Node node , E e){
        if(node == null){
            size ++;
            return new Node(e);
        }
        if(e.compareTo(node.e)<0){
            node.left = add(node.left , e);
        }else if(e.compareTo(node.e)>0){
            node.right = add(node.right , e);
        }
        return node;
    }

    //前序遍历
    public void preOrder(){
        preOrder(root);
    }

    //前序遍历以node为根的二分搜索树,递归算法
    private void preOrder(Node node){
        if(node == null){
            return;
        }
        System.out.println(node.e);
        preOrder(node.left);
        preOrder(node.right);
    }

    //中序遍历以node为根的二分搜索树
    public void inOrder(){
        inOrder(root);
    }

    private void inOrder(Node node){
        if(node == null) {
            return;
        }

        inOrder(node.left);
        System.out.println(node.e);
        inOrder(node.right);
    }

    //后序遍历以node为根的二分搜索树
    public void postOrder(){
        postOrder();
    }

    private void postOrder(Node node){
        if(node == null){
            return;
        }

        postOrder(node.left);
        postOrder(node.right);
        System.out.println(node.e);
    }

    public void preOrderNR(){
        Stack<Node> stack = new LinkedListStack<>();
        stack.push(root);
        while(!stack.isEmpty()){
            Node cur = stack.pop();
            System.out.println(cur.e);
            if(cur.right != null){
                stack.push(cur.right);
            }
            if(cur.left != null){
                stack.push(cur.left);
            }
        }
    }

    public void levelOrder(){
        Queue<Node> q = new LinkedList<>();
        q.add(root);
        while(!q.isEmpty()){
            Node cur = q.remove();
            System.out.println(cur.e);

            if(cur.left != null){
                q.add(cur.left);
            }
            if(cur.right != null){
                q.add(cur.right);
            }
        }
    }

    public E minimum(){
        if(size == 0){
            throw new IllegalArgumentException("BST is empty");
        }
        return minimum(root).e;
    }

    private Node minimum(Node node){
        if(node.left == null){
            return node;
        }
        return minimum(node.left);
    }

    public E maximum(){
        if(size == 0){
            throw new IllegalArgumentException("BST is empty");
        }
        return minimum(root).e;
    }

    private Node maximum(Node node){
        if(node.right == null){
            return node;
        }
        return minimum(node.right);
    }
    //从二分搜索树中删除最小值所在的节点,返回最小值
    public E removeMin(){
        E ret = minimum();
        removeMin(root);
        return ret;
    }


    private Node removeMin(Node node){
        if(node.left == null){
            Node rightNode = node.right;
            node.right = null;
            size --;
            return rightNode;
        }

        node.left = removeMin(node.left);
        return node;
    }

    //从二分搜索树中删除最大值所在的节点,返回最大值
    //从二分搜索树中删除最小值所在的节点,返回最小值
    public E removeMax(){
        E ret = minimum();
        removeMax(root);
        return ret;
    }


    private Node removeMax(Node node){
        if(node.right == null){
            Node leftNode = node.left;
            node.left = null;
            size --;
            return leftNode;
        }

        node.right = removeMax(node.right);
        return node;
    }

    // 从二分搜索树中删除元素为e的节点
    public void remove(E e){
        root = remove(root , e);
    }

    // 删除以node为根的二分搜索树中值为e的节点,递归算法
    // 返回删除节点后新的二分搜索树的根
    private Node remove(Node node , E e){
        if(node == null){
            return null;
        }

        if(e.compareTo(node.e) < 0){
            node.left = remove(node.left , e);
            return node;
        } else if(e.compareTo(node.e) > 0){
            node.right = remove(node.right , e);
            return node;
        } else{ // e == node.e
            //待删除节点左子树为空的情况
            if(node.left == null){
                Node rightNode = node.right;
                node.right = null;
                size --;
                return rightNode;
            }
            //待删除节点右子树为空的情况
            if(node.right == null){
                Node leftNode = node.left;
                node.left = null;
                size --;
                return leftNode;
            }

            // 待删除节点左右子树军部为空的情况
            // 找到比带删除节点大的最小节点,即待删除节点右子树的最小节点
            // 用这个节点顶替待删除节点的位置
            Node successor = minimum(node.right);
            successor.right = removeMin(node.right);
            successor.left = node.left;
            node.left = node.right = null;
            return successor;
        }
    }


    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        generateBSTString(root , 0 , res);
        return res.toString();
    }

    private void generateBSTString(Node node , int depth , StringBuilder res){
        if(node == null){
            res.append(generateDepthString(depth)+"null\n");
            return;
        }
        res.append(generateDepthString(depth)+node.e+"\n");
        generateBSTString(node.left , depth+1 , res);
        generateBSTString(node.right , depth +1 , res);
    }

    private String generateDepthString(int depth){
        StringBuilder res = new StringBuilder();
        for(int i = 0;i<depth;i++){
            res.append("--");
        }
        return res.toString();
    }
}

集合和映射 Set and Map

树映射(TreeMap):

package 映射;

import BST.BST;

public class BSTMap<K extends Comparable<K>,V> implements Map<K , V>{

    private class Node{
        public K key;
        public V value;
        public Node left , right;

        public Node(K key , V value){
            this.key = key;
            this.value = value;
            left = null;
            right = null;
        }

    }
    private Node root;
    private int size;

    public BSTMap(){
        root = null;
        size = 0;
    }

    @Override
    public int getSize(){
        return size;
    }

    @Override
    public boolean isEmpty(){
        return size == 0;
    }

    @Override
    public void add(K key , V value){
        root = add(root , key , value);
    }

    @Override
    public V remove(K key) {
        Node node = getNode(root , key);
        if(node != null){
            root = remove(root , key);
            return node.value;
        }

        return null;
    }

    private Node remove(Node node, K key){
        if(node == null){
            return null;
        }

        if(key.compareTo(node.key) < 0){
            node.left = remove(node.left , key);
            return node;
        } else if(key.compareTo(node.key) > 0){
            node.right = remove(node.right , key);
            return node;
        } else{ // e == node.e
            //待删除节点左子树为空的情况
            if(node.left == null){
                Node rightNode = node.right;
                node.right = null;
                size --;
                return rightNode;
            }
            //待删除节点右子树为空的情况
            if(node.right == null){
                Node leftNode = node.left;
                node.left = null;
                size --;
                return leftNode;
            }

            // 待删除节点左右子树军部为空的情况
            // 找到比带删除节点大的最小节点,即待删除节点右子树的最小节点
            // 用这个节点顶替待删除节点的位置
            Node successor = minimum(node.right);
            successor.right = removeMin(node.right);
            successor.left = node.left;
            node.left = node.right = null;
            return successor;
        }
    }

    private Node removeMin(Node node){
        if(node.left == null){
            Node rightNode = node.right;
            node.right = null;
            size --;
            return rightNode;
        }

        node.left = removeMin(node.left);
        return node;
    }

    private Node minimum(Node node){
        if(node.left == null){
            return node;
        }
        return minimum(node.left);
    }

    @Override
    public boolean contains(K key) {
        return getNode(root , key) != null;
    }

    @Override
    public V get(K key, V newValue) {
        Node node = getNode(root , key);
        return node == null ? null : node.value;
    }

    @Override
    public void set(K key, V newValue) {
        Node node = getNode(root , key);
        if(node == null){
            throw  new IllegalArgumentException(key + "doesn't exist!");
        }
        node.value = newValue;
    }

    private Node add(Node node , K key , V value){
        if(node == null){
            size++;
            return new Node(key ,value);
        }

        if(key.compareTo(node.key)<0){
            node.left = add(node.left , key , value);
        }else if(key.compareTo(node.key)>0){
            node.right = add(node.right , key , value);
        }else {
            node.value = value;
        }
        return node;
    }

    private Node getNode(Node node , K key){
        if(node == null){
            return null;
        }

        if(key.compareTo(node.key) == 0){
            return node;
        }else if(key.compareTo(node.key) < 0){
            return getNode(node.left , key);
        }else {
            return getNode(node.right , key);
        }
    }


}

优先队列

堆实现:

package;

import 数组.DynamicArray;

public class MaxHeap<E extends Comparable<E>> {

    private DynamicArray<E> data;

    public MaxHeap(int capacity){
        data = new DynamicArray<>(capacity);
    }

    public MaxHeap(E[] arr){
        data = new DynamicArray<>(arr);
        for(int i = parent(arr.length -1);i>=0;i--){
            siftDown(i);
        }
    }

    public MaxHeap(){
        data = new DynamicArray<>();
    }

    public int size(){
        return data.getSize();
    }

    public boolean isEmpty(){
        return data.isEmpty();
    }

    private int parent(int index){
        if(index == 0){
            throw new IllegalArgumentException("index -0 doesn't have parent");
        }
        return (index - 1)/2;
    }

    private int leftChild(int index){
        return index * 2 + 1;
    }

    private int rightChild(int index){
        return index*2 +2;
    }

    //向堆中添加元素
    public void add(E e){
        data.addLast(e);
        siftUp(data.getSize() - 1);
    }

    private void siftUp(int k){
        while(k >0 && data.get(parent(k)).compareTo(data.get(k)) < 0) {
            data.swap(k , parent(k));
            k = parent(k);
        }
    }

    public E findMax(){
        if(data.getSize()==0){
            throw new IllegalArgumentException("Can not findMax when heap is empty!");
        }
        return data.get(0);
    }

    public E extractMax(){
        E ret = findMax();

        data.swap(0 , data.getSize() - 1);
        data.remove(data.getSize()-1);

        siftDown(0);

        return ret;
    }


    private void siftDown(int k){
        while(leftChild(k) < data.getSize()){
            int j = leftChild(k);
            if(j + 1 < data.getSize() && data.get(j + 1).compareTo(data.get(j)) > 0){
                j = rightChild(k);
                //data[j] 是 leftChild he rightChild中的最大值
            }
            if (data.get(k).compareTo(data.get(j)) >= 0){
                break;
            }

            data.swap(k , j);
            k = j;
        }
    }

    //去出堆中最大元素,并且替换成元素e
    public E replace(E e){
        E ret = findMax();
        data.set(0 , e);
        siftDown(0);
        return ret;
    }
}

线段树

package;

public class SegmentTree<E>{

    private E[] tree;
    private E[] data;
    private Merger<E> merger;

    public SegmentTree(E[] arr , Merger<E> merger){
        this.merger = merger;

        data = (E[])new Object[arr.length];
        for(int i = 0;i<arr.length;i++){
            data[i] = arr[i];
        }

        tree = (E[]) new Object[4 * arr.length];
        buildSegmentTree(0 , 0 , data.length -1);
    }

    // 在treeIndex的位置创建表示区间[l....r]的线段树
    private void buildSegmentTree(int treeIndex , int l , int r){
        if(l == r){
            tree[treeIndex] = data[l];
            return;
        }

        int leftTreeIndex = leftChild(treeIndex);
        int rightTreeIndex = rightChild(treeIndex);

        int mid = l + (r - l) /2;
        buildSegmentTree(leftTreeIndex , l , mid);
        buildSegmentTree(rightTreeIndex , mid +1 , r);

        tree[treeIndex] = merger.merge(tree[leftTreeIndex] , tree[rightTreeIndex]);
    }

    public int getSize(){
        return data.length;
    }

    public E get(int index){
        if(index < 0 || index >= data.length){
            throw new IllegalArgumentException("Index is illegal");
        }
        return data[index];
    }

    private int leftChild(int index){
        return 2*index +1;
    }

    private int rightChild(int index){
        return 2*index +2;
    }

    public E query(int queryL , int queryR){
        if(queryL <0 || queryL >= data.length ||
                queryR < 0 || queryR >= data.length || queryL > queryR){
            throw new IllegalArgumentException("Index is illegal");
        }
        return query( 0 , 0 ,data.length -1 , queryL , queryR);
    }

    //在以treeID为根的线段树中[l...r]的范围里,搜索区间[queryL...queryR]的值
    private E query(int treeIndex,  int l , int r , int queryL , int queryR){
        if(l == queryL && r == queryR){
            return tree[treeIndex];
        }

        int mid = l + (r - l) /2;
        int leftTreeIndex = leftChild(treeIndex);
        int rightTreeIndex = rightChild(treeIndex);

        if(queryL >= mid+1){
            return query(rightTreeIndex , mid +1 , r , queryL , queryR);
        }else if(queryR <= mid){
            return query(leftTreeIndex , l , mid , queryL , queryR);
        }

        E leftResult = query(leftTreeIndex, l, mid, queryL, mid);
        E rightResult = query(rightTreeIndex , mid + 1 , r , mid+1 , queryR);
        return merger.merge(leftResult , rightResult);
    }

    public void set(int index , E e){
        if(index < 0 || index >= data.length){
            throw new IllegalArgumentException("Index is illegal");
        }

        data[index] = e;
        set(0, 0, data.length-1, index, e);
    }

    //在以treeIndex为根的线段树中更新index的值为e
    private void set(int treeIndex , int l , int r , int index , E e){
        if(l == r){
            tree[treeIndex] = e;
            return;
        }

        int mid = l + (r - l)/2;
        int leftTreeIndex = leftChild(treeIndex);
        int rightTreeIndex = rightChild(treeIndex);

        if(index >= mid + 1){
            set(rightTreeIndex, mid + 1, r, index, e);
        }else {
            set(leftTreeIndex, l, mid, index, e);
        }

        tree[treeIndex] = merger.merge(tree[leftTreeIndex], tree[rightTreeIndex]);
    }

    @Override
    public String toString(){
        StringBuilder res = new StringBuilder();
        res.append('[');
        for(int i = 0;i<tree.length;i++){
            if(tree[i] !=null){
                res.append(tree[i]);
            }else {
                res.append("null");
            }

            if(i != tree.length -1){
                res.append(',');
            }
        }
        res.append(']');
        return res.toString();
    }
}

Trie

对于Trie来说,经常用来处理字符串

package;


import java.util.TreeMap;

public class Trie {
    private class Node{
        boolean isWord;
        TreeMap<Character, Node> next;

        public Node(boolean isWord){
            this.isWord = isWord;
            next = new TreeMap<>();
        }

        public Node(){
            this(false);
        }
    }

    private Node root;
    private int size;

    public Trie(){
        root = new Node();
        size = 0;
    }

    public int getSize(){
        return size;
    }

    public void add(String word){
        Node cur = root;
        for(int i =0;i<word.length();i++){
            char c = word.charAt(i);
            if(cur.next.get(c) == null){
                cur.next.put(c , new Node());
            }
            cur = cur.next.get(c);
        }
        if(!cur.isWord){
            cur.isWord = true;
            size++;
        }
    }

    public boolean contains(String word){
        Node cur = root;
        for(int i = 0; i<word.length();i++){
            char c = word.charAt(i);
            if(cur.next.get(c) == null){
                return false;
            }
            cur = cur.next.get(c);
        }
        return cur.isWord;
    }

    /**
     * 查询是否有单词以prefix为前缀
     * */
    public boolean isPrefix(String prefix){
        Node cur = root;
        for(int i = 0;i<prefix.length();i++){
            char c = prefix.charAt(i);
            if(cur.next.get(c) == null){
                return false;
            }
            cur = cur.next.get(c);
        }
        return true;
    }

    public boolean search(String word){

        return match(root , word , 0);
    }

    private boolean match(Node node , String word , int index){
        if(index == word.length()){
            return node.isWord;
        }

        char c = word.charAt(index);
        if(c !='.'){
            if(node.next.get(c) == null){
                return false;
            }
            return match(node.next.get(c) , word , index +1);
        }else {
            for(char nextChar:node.next.keySet()){
                if(match(node.next.get(nextChar) , word , index+1)){
                    return true;
                }
            }
            return false;
        }
    }

}

并查集

由孩子指向父亲

package UF;

import java.util.Collections;

public class UnionFind5 implements UF{
    private int[] parent;
    private int[] rank;

    public UnionFind5(int size){
        parent = new int[size];
        rank = new int[size];

        for(int i = 0;i<size;i++){
            parent[i] = i;
            rank[i] = 1;
        }
    }

    @Override
    public int getSize(){
        return parent.length;
    }

    private int find(int p){

        if(p < 0 || p >= parent.length){
            throw new IllegalArgumentException("p is out of bound");
        }

        while(p != parent[p]){
            parent[p] = parent[parent[p]];
            p = parent[p];
        }
        return p;
    }

    @Override
    public boolean isConnected(int p , int q){
        return find(p) == find(q);
    }

    @Override
    public void unionElements(int p , int q){
        int pRoot = find(p);
        int qRoot = find(q);

        if(pRoot == qRoot){
            return;
        }

        //根据两个元素所在树的元素个数不同判断合并方向
        //将元素个数少的集合合并到元素个数多的集合上
        if(rank[pRoot] < rank[qRoot]){
            parent[pRoot] = qRoot;
        }else if(rank[qRoot] < rank[pRoot]){
            parent[qRoot] = pRoot;
        }else{
            parent[qRoot] = pRoot;
            rank[pRoot] += 1;
        }
    }
}

AVL

平衡二叉树:对于任意一个节点,左子树和右子树的高度差不能超过1

平衡二叉树的高度和节点数量之间的关系也是O(logn)的

package;


import java.util.ArrayList;

public class AVLTree<K extends Comparable<K>,V>{

    private class Node{
        public K key;
        public V value;
        public Node left , right;
        public int height;

        public Node(K key , V value){
            this.key = key;
            this.value = value;
            left = null;
            right = null;
            height = 1;
        }

    }
    private Node root;
    private int size;

    public AVLTree(){
        root = null;
        size = 0;
    }

    //获得node节点的高度
    private int getHeight(Node node){
        if(node == null){
            return 0;
        }
        return node.height;
    }

    //获取平衡因子
    public int getBalanceFactor(Node node){
        if(node == null){
            return 0;
        }
        return getHeight(node.left) - getHeight(node.right);
    }

    public int getSize(){
        return size;
    }


    public boolean isEmpty(){
        return size == 0;
    }

    // 判断该二叉树是否是一颗二分搜索树
    public boolean isBST(){
        ArrayList<K> keys = new ArrayList<>();
        inOrder(root , keys);

        for(int i = 1; i<keys.size();i++){
            if(keys.get(i-1).compareTo(keys.get(i))>0){
                return false;
            }
        }
        return true;
    }

    private void inOrder(Node node , ArrayList<K> keys){
        if(node == null){
            return;
        }

        inOrder(node.left , keys);
        keys.add(node.key);
        inOrder(node.right , keys);
    }

    // 判断该二叉树是不是一颗平衡二叉树
    public boolean isBalanced(){
        return isBalanced(root);
    }

    // 判断以Node为根的二叉树是否是一棵平衡二叉树,递归算法
    private boolean isBalanced(Node node){
        if(node == null){
            return true;
        }

        int balanceFactor = getBalanceFactor(node);
        if(Math.abs(balanceFactor) > 1){
            return false;
        }
        return isBalanced(node.left) && isBalanced(node.right);
    }


    public void add(K key , V value){
        root = add(root , key , value);
    }


    public V remove(K key) {
        Node node = getNode(root , key);
        if(node != null){
            root = remove(root , key);
            return node.value;
        }

        return null;
    }

    private Node remove(Node node, K key){
        if(node == null){
            return null;
        }

        Node retNode;

        if(key.compareTo(node.key) < 0){
            node.left = remove(node.left , key);
            retNode = node;
        } else if(key.compareTo(node.key) > 0){
            node.right = remove(node.right , key);
            retNode = node;
        } else{ // e == node.e
            //待删除节点左子树为空的情况
            if(node.left == null){
                Node rightNode = node.right;
                node.right = null;
                size --;
                retNode = rightNode;
            }
            //待删除节点右子树为空的情况
            else if(node.right == null){
                Node leftNode = node.left;
                node.left = null;
                size --;
                retNode = leftNode;
            }else {
            // 待删除节点左右子树军部为空的情况
            // 找到比带删除节点大的最小节点,即待删除节点右子树的最小节点
            // 用这个节点顶替待删除节点的位置
            Node successor = minimum(node.right);
            successor.right = remove(node.right , successor.key);
            successor.left = node.left;
            node.left = node.right = null;
            retNode = successor;
            }
        }

        if(retNode == null){
            return null;
        }

        //更新height
        retNode.height = 1 + Math.max(getHeight(retNode.left) , getHeight(retNode.right));

        //计算平衡因子
        int balanceFactor = getBalanceFactor(retNode);
        if(Math.abs(balanceFactor)>1){
            System.out.println("unbalanced:"+balanceFactor);
        }

        // 平衡维护
        // LL
        if(balanceFactor > 1 && getBalanceFactor(retNode.left) >= 0){
            return rightRotate(retNode);
        }

        // RR
        if(balanceFactor < -1 && getBalanceFactor(retNode.right) <= 0){
            return leftRotate(retNode);
        }

        //LR
        if(balanceFactor > 1 && getBalanceFactor(retNode.left) < 0){
            node.left = leftRotate(retNode.left);
            return rightRotate(retNode);
        }

        //RL
        if(balanceFactor < -1 && getBalanceFactor(retNode.right) > 0){
            node.right = rightRotate(retNode.right);
            return rightRotate(retNode);
        }

        return retNode;
    }



    private Node minimum(Node node){
        if(node.left == null){
            return node;
        }
        return minimum(node.left);
    }


    public boolean contains(K key) {
        return getNode(root , key) != null;
    }


    public V get(K key, V newValue) {
        Node node = getNode(root , key);
        return node == null ? null : node.value;
    }


    public void set(K key, V newValue) {
        Node node = getNode(root , key);
        if(node == null){
            throw  new IllegalArgumentException(key + "doesn't exist!");
        }
        node.value = newValue;
    }

    private Node add(Node node , K key , V value){
        if(node == null){
            size++;
            return new Node(key ,value);
        }

        if(key.compareTo(node.key)<0){
            node.left = add(node.left , key , value);
        }else if(key.compareTo(node.key)>0){
            node.right = add(node.right , key , value);
        }else {
            node.value = value;
        }

        //更新height
        node.height = 1 + Math.max(getHeight(node.left) , getHeight(node.right));

        //计算平衡因子
        int balanceFactor = getBalanceFactor(node);
        if(Math.abs(balanceFactor)>1){
            System.out.println("unbalanced:"+balanceFactor);
        }

        // 平衡维护
        // LL
        if(balanceFactor > 1 && getBalanceFactor(node.left) >= 0){
            return rightRotate(node);
        }

        // RR
        if(balanceFactor < -1 && getBalanceFactor(node.right) <= 0){
            return leftRotate(node);
        }

        //LR
        if(balanceFactor > 1 && getBalanceFactor(node.left) < 0){
            node.left = leftRotate(node.left);
            return rightRotate(node);
        }

        //RL
        if(balanceFactor < -1 && getBalanceFactor(node.right) > 0){
            node.right = rightRotate(node.right);
            return rightRotate(node);
        }
        return node;
    }

    private Node leftRotate(Node y){
        Node x = y.right;
        Node T2 = x.left;

        //向左旋转过程
        x.left = y;
        y.right = T2;

        //更新height
        y.height = Math.max(getHeight(y.left) , getHeight(y.right)) + 1;
        x.height = Math.max(getHeight(x.left) , getHeight(x.right)) + 1;

        return x;
    }

    private Node rightRotate(Node y){
        Node x = y.left;
        Node T3 = x.right;

        //向右旋转过程
        x.right = y;
        y.left = T3;

        //更新height
        y.height = Math.max(getHeight(y.left) , getHeight(y.right)) + 1;
        x.height = Math.max(getHeight(x.left) , getHeight(x.right)) + 1;

        return x;
    }

    private Node getNode(Node node , K key){
        if(node == null){
            return null;
        }

        if(key.compareTo(node.key) == 0){
            return node;
        }else if(key.compareTo(node.key) < 0){
            return getNode(node.left , key);
        }else {
            return getNode(node.right , key);
        }
    }


}

红黑树

每个节点或者是红色的,或者是黑色的

根节点是黑色的

每一个叶子节点(最后的空节点)是黑色的

如果一个节点是红色的,那么它的孩子节点都是黑色的

从任意一个节点到叶子节点,经过的黑色节点是一样的

概念:图是由顶点和边组成的数据结构

在有向图中,细分为入度和出度。边可以有权重,代表从源顶点到目标顶点的距离、费用、时间或者其他度量

以上就是近期学习的所有API,红黑树和图没有实现代码是因为这两个实现比较复杂,而且图的应用算法基本上都是困难级别。所以可能会在之后的博客中单开几篇去讲他们。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值