算法

[数据结构][算法][面向对象][Java]
https://github.com/z8g/common

文章目录

1 设计接口

1.1 容器接口Container

package ds;
import java.util.NoSuchElementException;
public interface Container{
   
    int size();
    
    default boolean isEmpty(){
   
        return size() == 0;
    }
    default void notEmptyCheck() {
   
        if (isEmpty()) {
   
            throw new NoSuchElementException("size == 0");
        }
    }
}

1.2 背包接口Bag

package ds;

public interface Bag<T> extends Container {
   
    void add(T data);
}


1.3 栈接口Stack

package ds;

public interface Stack<T>extends Container {
   
    void push(T data);
    T pop();
    T peek();
}

1.4 队列接口Queue

package ds;

public interface Queue<T> extends Container {
   
    T peek();
    void enqueue(T data);
    T dequeue();
}

1.5 Union-Find算法接口UF

package ds;

public interface UF {
   
    int size();
    int find(int p);
    boolean connected(int p, int q);
    void union(int p, int q);
    default void validate(int p, int n) {
   
        if (p < 0 || p >= n) {
   
            throw new IllegalArgumentException("p>=0 && p<n");
        }
    }
}

2 实现接口

为数组和链表定义了公共的结点和迭代器实现。

2.1 结点类Node

package ds.util;

public class Node<T> {
   
   public T data;
   public Node<T> next;
}

2.2 数组迭代器ArrayIterator

package ds.util;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class ArrayIterator<T> implements Iterator<T> {
   
    private int i;
    private final int size;
    private final T[] array;
    public ArrayIterator(T[] array, int size) {
   
        this.array = array;
        this.size = size;
    }
    @Override
    public boolean hasNext() {
   
        return i < size;
    }
    @Override
    public T next() {
   
        if (!hasNext()) {
   
            throw new NoSuchElementException();
        }
        return array[i++];
    }
}

2.3 链表迭代器ListIterator

package ds.util;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class ListIterator<T> implements Iterator<T> {
   
    private Node<T> current;
    public ListIterator(Node<T> first) {
   
        current = first;
    }
    @Override
    public boolean hasNext() {
   
        return current != null;
    }
    @Override
    public T next() {
   
        if (!hasNext()) {
   
            throw new NoSuchElementException();
        }
        T result = current.data;
        current = current.next;
        return result;
    }
}


2.4 背包(Bag)的实现

背包(Bag)是一种不支持从中删除元素的集合数据类型。

2.4.1 能动态调整数组大小的Bag
package ds.impl;
import ds.Bag;
import java.util.Iterator;
import ds.util.ArrayIterator;

public class ArrayBag<T> implements Iterable<T>,Bag<T> {
   
    private T[] array;
    private int size;
    public ArrayBag() {
   
        array = (T[]) new Object[2];
        size = 0;
    }
    @Override
    public int size() {
   
        return size;
    }
    @Override
    public void add(T data) {
   
        if (size == array.length) {
   
            resize(2 * array.length);
        }
        array[size++] = data;
    }
    private void resize(int capacity) {
   
        assert capacity >= 0;
        T[] tmp = (T[]) new Object[capacity];
        System.arraycopy(array, 0, tmp, 0, size);
        array = tmp;
    }
    
    @Override
    public Iterator<T> iterator() {
   
        return new ArrayIterator(array,size);
    }
    
}
2.4.2 链式Bag的实现
package ds.impl;
import ds.util.Node;
import ds.Bag;
import java.util.Iterator;
import ds.util.ListIterator;

public class LinkedBag<T> implements Iterable<T>, Bag<T> {
   
    private Node<T> first;
    private int size;
    public LinkedBag() {
   
        first = null;
        size = 0;
    }
    @Override
    public int size() {
   
        return size;
    }
    @Override
    public void add(T data) {
   
        Node<T> old = first;
        first = new Node<>();
        first.data = data;
        first.next = old;
        size++;
    }
    @Override
    public String toString() {
   
        StringBuilder s = new StringBuilder();
        for (T data : this) {
   
            s.append(data).append(' ');
        }
        return s.toString();
    }
    @Override
    public Iterator<T> iterator() {
   
        return new ListIterator(first);
    }
}

2.5 栈(Stack)的实现

栈(Stack)是一种先进后出的数据类型。

2.5.1 能动态调整数组大小的Stack
package ds.impl;
import ds.Stack;
import java.util.Iterator;
import ds.util.ArrayIterator;

public class ArrayStack<T> implements Iterable<T>,Stack<T> {
   
    private T[] array;
    private int size;
    
    public ArrayStack(){
   
        array = (T[]) new Object[2];
        size = 0;
    }
    
    
    @Override
    public Iterator<T> iterator() {
   
        return new ArrayIterator(array,size);
    }
    @Override
    public int size() {
   
        return size;
    }
    @Override
    public void push(T data) {
   
        if(size == array.length){
   
            resize(2* array.length);
        }
        array[size++] = data;
    }
    private void resize(int capacity) {
   
        assert capacity >= size;
        T[] tmp = (T[]) new Object[capacity];
        System.arraycopy(array, 0, tmp, 0, size);
        array = tmp;
    }
    
    @Override
    public T pop() {
   
        notEmptyCheck();
        T result = array[size-1];
        array[size-1] = null;
        size--;
        if(size>0 && size == array.length/4){
   
            resize(array.length/2);
        }
        return result;
    }
    
    @Override
    public T peek() {
   
        notEmptyCheck();
        return array[size-1];
    }
}
2.5.2 链式Stack的实现
package ds.impl;
import ds.util.Node;
import ds.Stack;
import java.util.Iterator;
import ds.util.ListIterator;

public class LinkedStack<T> implements Iterable<T>,Stack<T> {
   
    private Node<T> first;
    private int size;
    public LinkedStack() {
   
        first = null;
        size = 0;
    }
    @Override
    public int size() {
   
        return size;
    }
    /**
     * 向栈中推入一个新元素
     *
     * @param data 新元素
     */
    @Override
    public void push(T data) {
   
        Node<T> oldFirst = first;
        first = new Node<>();
        first.data = data;
        first.next = oldFirst;
        size++;
    }
    /**
     * 从栈中弹出栈首元素
     *
     * @return 栈首元素
     */
    @Override
    public T pop() {
   
        notEmptyCheck();
        T result = first.data;
        first = first.next;
        size--;
        return result;
    }
    /**
     * 查看栈首元素
     * @return 栈首元素
     */
    @Override
    public T peek() {
   
        notEmptyCheck();
        return first.data;
    }
    @Override
    public String toString() {
   
        StringBuilder s = new StringBuilder();
        for (T data : this) {
   
            s.append(data).append(' ');
        }
        return s.toString();
    }
    @Override
    public Iterator<T> iterator() {
   
        return new ListIterator(first);
    }
}

2.6 队列(Queue)的实现

队列(Queue)是一种先进先出的数据类型。

2.6.1 能动态调整数组大小的Queue
package ds.impl;
import ds.Queue;
import java.util.Iterator;

public class ArrayQueue<T> implements Iterable<T>,Queue<T> {
   
    private T[] array;
    private int size;
    private int first;
    private int last;
    public ArrayQueue() {
   
        array = (T[]) new Object[2];
        size = 0;
        first = 0;
        last = 0;
    }
    @Override
    public int size() {
   
        return size;
    }
    @Override
    public void enqueue(T data) {
   
        if (size == array.length) {
   
            resize(2 * array.length);
        }
        array[last++] = data;
        if (last == array.length) {
   
            last = 0;
        }
        size++;
    }
    @Override
    public T dequeue() {
   
        notEmptyCheck();
        T result = array[first];
        array[first] = null;
        size--;
        first++;
        if (first == array.length) {
   
            first = 0;
        }
        if (size > 0 && size == array.length / 4) {
   
            resize(array.length / 2);
        }
        return result;
    }
    
    @Override
    public T peek(){
   
        notEmptyCheck();
        return array[first];
    }
    private void resize(int capacity) {
   
        assert capacity >= size;
        T[] tmp = (T[]) new Object[capacity];
        for (int i = 0; i < size; i++) {
   
            tmp[i] = array[(first + i) % array.length];
        }
        array = tmp;
        first = 0;
        last = size;
    }
    @Override
    public Iterator<T> iterator() {
   
        return new ds.util.ArrayIterator(array,size);
    }
}
2.6.2 链式Queue的实现
package ds.impl;
import ds.util.Node;
import ds.Queue;
import java.util.Iterator;
import ds.util.ListIterator;

public class LinkedQueue<T> implements Iterable<T>, Queue<T> {
   
    private Node<T> first;
    private Node<T> last;
    private int size;
    public LinkedQueue() {
   
        first = null;
        last = null;
        size = 0;
    }
    @Override
    public int size() {
   
        return size;
    }
    @Override
    public T peek() {
   
        notEmptyCheck();
        return first.data;
    }
    @Override
    public void enqueue(T data) {
   
        Node<T> oldLast = last;
        last = new Node<>();
        last.data = data;
        last.next = null;
        if (isEmpty()) {
   
            first = last;
        } else {
   
            oldLast.next = last;
        }
        size++;
    }
    @Override
    public T dequeue() {
   
        notEmptyCheck();
        T result = first.data;
        first = first.next;
        size--;
        if (isEmpty()) {
   
            last = null;
        }
        return result;
    }
    @Override
    public String toString() {
   
        StringBuilder s = new StringBuilder();
        for (T data : this) {
   
            s.append(data).append(' ');
        }
        return s.toString();
    }
    @Override
    public Iterator<T> iterator() {
   
        return new ListIterator(first);
    }
}

2.7 Union-Find算法的实现

并查集(Union-Find)是解决动态连通性问题的一类非常高效的数据结构。

2.7.1 DefaultUF
package ds.impl;
import ds.UF;

public class DefaultUF implements UF {
   
    private int[] parent;
    private byte[] rank;
    private int size;
    public DefaultUF(int n) {
   
        if (n < 0) {
   
            throw new IllegalArgumentException();
        }
        size = n;
        parent = new int[n];
        rank = new byte[n];
        for (int i = 0; i < n; i++) {
   
            parent[i] = i;
            rank[i] = 0;
        }
    }
    @Override
    public int find(int p) {
   
        validate(p, parent.length);
        while (p != parent[p]) {
   
            parent[p] = parent[parent[p]];
            p = parent[p];
        }
        return p;
    }
    @Override
    public int size() {
   
        return size;
    }
    @Override
    public boolean connected(int p, int q) {
   
        return find(p) == find(q);
    }
    @Override
    public void union(int p, int q) {
   
        int rootP = find(p);
        int rootQ = find(q);
        if (rootP == rootQ) {
   
            return;
        }
        if (rank[rootP] < rank[rootQ]) {
   
            parent[rootP] = rootQ;
        } else if (rank[rootQ] > rank[rootP]) {
   
            parent[rootQ] = rootP;
        } else {
   
            parent[rootQ] = rootP;
            rank[rootP]++;
        }
        size--;
    }
}
2.7.2 QuickFindUF
package ds.impl;
import ds.UF;

public class QuickFindUF implements UF {
   
    private final int[] id;
    private int size;
    public QuickFindUF(int n) {
   
        size = n;
        id = new int[n];
        for (int i = 0; i < n; i++) {
   
            id[i] = i;
        }
    }
    @Override
    public int size() {
   
        return size;
    }
    @Override
    public int find(int p) {
   
        validate(p, id.length);
        return id[p];
    }
    @Override
    public boolean connected(int p, int q) {
   
        validate(p, id.length);
        validate(q, id.length);
        return id[p] == id[q];
    }
    @Override
    public void union(int p, int q) {
   
        validate(p, id.length);
        validate(q, id.length);
        int pID = id[p];
        int qID = id[q];
        if (pID == qID) {
   
            return;
        }
        for (int i = 0; i < id.length; i++) {
   
            if (id[i] == pID) {
   
                id[i] = qID;
            }
        }
        size--;
    }
}
2.7.3 QuickUnionUF
package ds.impl;
import ds.UF;
public class QuickUnionUF implements UF {
   
    private final int[] parent;
    private int size;
    public QuickUnionUF(int n) {
   
        parent = new int[n];
        size = n;
        for (int i = 0; i < n; i++) {
   
            parent[i] = i;
        }
    }
    @Override
    public int size() {
   
        return size;
    }
    @Override
    public int find(int p) {
   
        validate(p, parent.length);
        while (p != parent[p]) {
   
            p = parent[p];
        }
        return p;
    }
    @Override
    public boolean connected(int p, int q) {
   
        return find(p) == find(q);
    }
    @Override
    public void union(int p, int q) {
   
        int rootP = find(p);
        int rootQ = find(q);
        if (rootP == rootQ) {
   
            return;
        }
        parent[rootP] = rootQ;
        size--;
    }
}
2.7.4 WeightedQuickUnionUF

加权 quick-union算法,是目前所有实现中最优的算法

package ds.impl;
import ds.UF;

public class WeightedQuickUnionUF implements UF {
   
    private final int[] parent;
    private final int[] num;
    private int size;
    public WeightedQuickUnionUF(int n) {
   
        size = n;
        parent = new int[n];
        num = new int[n];
        for (int i = 0; i < n; i++) {
   
            parent[i] = i;
            num[i] = 1;
        }
    }
    @Override
    public int size() {
   
        return size;
    }
    @Override
    public int find(int p) {
   
        validate(p, parent.length);
        while (p != parent[p]) {
   
            p = parent[p];
        }
        return p;
    }
    @Override
    public boolean connected(int p, int q) {
   
        return find(p) == find(q);
    }
    @Override
    public void union(int p, int q) {
   
        int rootP = find(p);
        int rootQ = find(q);
        if (rootP == rootQ) {
   
            return;
        }
        // make smaller root point to larger one
        if (num[rootP] < num[rootQ]) {
   
            parent[rootP] = rootQ;
            num[rootQ] += num[rootP];
        } else {
   
            parent[rootQ] = rootP;
            num[rootP] += num[rootQ];
        }
        size--;
    }
}

2.8 测试

2.8.1 测试Stack

Dijkstra的双栈算数表达式求值算法

package test;
import java.util.Scanner;
import ds.impl.LinkedStack;

public class StackTest {
   
    public static void main(String[] args) {
   
        evaluate();
    }
    /**
     * Dijkstra的双栈算数表达式求值算法
     */
    public static void evaluate() {
   
        String str = "( 1 + ( ( 2.3 + 3 ) / ( sqrt ( 16 ) * ( 5 % 9 ) ) ) )";
        LinkedStack<String> opStack = new LinkedStack<>();
        LinkedStack<Double> valStack = new LinkedStack<>();
        Scanner scanner = new Scanner(str);
        while (scanner.hasNext()) {
   
            String s = scanner.next();
            System.out.print(s + ' ');
            switch (s) {
   
                case "+":
                case "-":
                case "*":
                case "/":
                case "%":
                case "sqrt":
                    opStack.push(s);
                    break;
                case "(":
                    break;
                case ")":
                    String op = opStack.pop();
                    double v = valStack.pop();
                    switch (op) {
   
                        case "+":
                            v = valStack.pop() + v;
                            break;
                        case "-":
                            v = valStack.pop() - v;
                            break;
                        case "*":
                            v = valStack.pop() * v;
                            break;
                        case "/":
                            v = valStack.pop() / v;
                            break;
                        case "%":
                            v = valStack.pop() % v;
                            break;
                        case "sqrt":
                            v = Math.sqrt(v);
                            break;
                        default:
                            break;
                    }
                    valStack.push(v);
                    break;
                default:
                    valStack.push(Double.parseDouble(s));
                    break;
            }
        }
        System.out.printf("= %f\n", valStack.pop());
    }
}
2.8.2 测试Union-Find
package test;
import ds.UF;
import ds.impl.DefaultUF;
import ds.impl.QuickFindUF;
import ds.impl.QuickUnionUF;

public class UFTest {
   
    public static void main(String[] args) {
   
        UF uf;
        int findResult;
        uf = new QuickFindUF(10);
        uf.union(4, 3);
        uf.union(3, 8);
        uf.union(6, 5);
        uf.union(9, 4);
        uf.union(2, 1);
        uf.union(5, 0);
        uf.union(7, 2);
        uf.union(6, 1);
        findResult = uf.find(3);
        System.out.println(findResult);
        System.out.println(uf.size());
        System.out.println(uf.connected(4, 3));
        System.out.println(uf.connected(9, 3));
        uf = new DefaultUF(10);
        uf.union(4, 3);
        uf.union(3, 8);
        uf.union(6, 5);
        uf.union(9, 4);
        uf.union(2, 1);
        uf.union(5, 0);
        uf.union(7, 2);
        uf.union(6, 1);
        findResult = uf.find(3);
        System.out.println(findResult);
        System.out.println(uf.size());
        System.out.println(uf.connected(4, 3));
        System.out.println(uf.connected(9, 3));
        uf = new QuickUnionUF(10);
        uf.union(4, 3);
        uf.union(3, 8);
        uf.union(6, 5);
        uf.union(9, 4);
        uf.union(2, 1);
        uf.union(5, 0);
        uf.union(7, 2);
        uf.union(6, 1);
        findResult = uf.find(3);
        System.out.println(findResult);
        System.out.println(uf.size());
        System.out.println(uf.connected(4, 3));
        System.out.println(uf.connected(9, 3));
    }
}

3 排序算法

3.1 定义排序工具的类结构

需要实现排序器,以及通过静态方法调用。

package util;
import java.util.Arrays
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值