数据结构与算法(持续更新ing)

50 阅读5分钟

1.二分查找

public class BinarySearch {
    /**
     * 二分查找基础版
     *
     * @param arr    待查找数组
     * @param target 目标值
     * @return 目标值的索引,-1为没有找到
     */
    public static int binarySearch(int[] arr, int target) {
        int i = 0, j = arr.length, m;
        while (i < j) {
            m = (i + j) >>> 1;
            if (target < arr[m])
                j = m;
            else if (arr[m] < target)
                i = m + 1;
            else
                return m;
        }
        return -1;

    }

    //遇到相同的查找最左边
    public static int leftMostBinarySearch(int[] arr, int target) {
        int i = 0, j = arr.length, m, candidate = -1;
        while (i <= j) {
            m = (i + j) >>> 1;
            if (target < arr[m])
                j = m - 1;
            else if (arr[m] < target)
                i = m + 1;
            else {
                candidate = m;
                j = m - 1;
            }
        }
        return candidate;

    }

    //右
    public static int rightMostBinarySearch(int[] arr, int target) {
        int i = 0, j = arr.length-1, m, candidate = -1;
        while (i <= j) {
            m = (i + j) >>> 1;
            if (target < arr[m])
                j = m - 1;
            else if (arr[m] < target)
                i = m + 1;
            else {
                candidate= m;
                i = m + 1;
            }
        }
        return candidate;

    }
    //递归二分
    public static int binarySearch(int[] arr, int target, int i, int j) {
        if (i > j) {
            return -1;
        }
        int m = (i + j) >>> 1;
        if (target > arr[m]) {
            return binarySearch(arr, target, m + 1, j);
        } else if (target < arr[m]) {
            return binarySearch(arr, target, i, m - 1);
        } else {
            return m;
        }
    }

    public static void main(String[] args) {
        int[] arr = new int[]{7, 12, 12, 12, 12, 12, 42, 43};
        int target = 12;
        int i = binarySearch(arr, target);
        System.out.println(i);

    }

}

2.链表

1.单向链表

//单向链表
public class SinglyLinkedList implements Iterable<Integer> {
    Node head; //头指针

    /**
     * 节点类
     */
    private static class Node {
        Integer value; //值
        Node next; //下一个节点

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

    }

    public void addFirst(int v) {
        head = new Node(v, head);
    }

    public void lastAdd(Integer v) {
        //如果头结点为空,直接添加
        if (head == null)
            head = new Node(v, null);
        else {
            Node p = head;
            while (p.next != null)
                p = p.next;
            p.next = new Node(v, null);
        }
    }

    public void print() {
        Node t = head;
        while (t != null) {
            System.out.println(t.value);
            t = t.next;
        }
    }

    public Node find(Integer index) {
        int i = 0;
        Node p = head;
        while (p != null) {
            if (i == index)
                return p;
            p = p.next;
            i++;
        }
        return null;
    }

    public Integer get(Integer index) {
        Node node = find(index);
        if (node == null) {
            throw getIllegalArgumentException(String.format("index[%d]不合法", index));
        }
        return node.value;
    }

    /**
     * 链表插入节点
     *
     * @param index
     * @param value
     */
    public void insert(Integer index, Integer value) {
        if (index == 0) {
            addFirst(value);
            return;
        }
        Node prev = find(index - 1);
        if (prev == null) {
            throw getIllegalArgumentException(String.format("插入位置[%d]非法", index));
        }
        prev.next = new Node(value, prev.next);
    }

    private static IllegalArgumentException getIllegalArgumentException(String index) {
        return new IllegalArgumentException(index);
    }

    /**
     * 删除头结点
     */
    public void delFirst() {
        if (head == null) {
            throw getIllegalArgumentException(String.format("链表为空%s", "1"));
        }
        head = head.next;
    }

    public void delTail(){

    }
    /**
     * 删除索引位置节点
     *
     * @param index
     */
    public void delByIndex(Integer index) {
        //判断是否是第一个节点
        if (index == 0) {
            delFirst();
            return;
        }
        //拿到删除目标节点的前一个节点
        Node node = find(index - 1);
        //判断前一个节点是不是为空,或者前一个节点是不是链表最后一个节点
        if (node == null || node.next == null)
            throw getIllegalArgumentException(String.format("索引位置[%d]非法", index));
        //判断是index否是最后一个节点
        if (node.next.next == null) {
            node.next = null;
            return;
        }
        //如果不是最后一个节点之间修改指针位置
        node.next = node.next.next;
    }
    @Override
    public Iterator<Integer> iterator() {

        return new Iterator<Integer>() {
            Node p = head;

            @Override
            public boolean hasNext() {
                return p != null;
            }

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

}

2.双向链表带哨兵版

public class DoublyLinkedListSentinel implements Iterable<Integer> {
    private Node head;
    private Node tail;


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

    /**
     * 按照索引查找节点
     *
     * @param index
     * @return
     */
    private Node findNode(int index) {
        int i = -1;
        Node p = head;
        while (p.next != tail) {
            if (i == index)
                return p;
            p = p.next;
            i++;
        }
        return null;
    }

    public void addFirst(int value) {
        Node node = new Node(head, value, head.next);
        head.next = node;
        node.next.prev = node;
    }

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

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

    public void removeLast() {
        Node preNode = tail.prev;
        if (preNode != head)
            throw illegalIndex(0);
        preNode.prev.next = tail;
        tail.prev = preNode.prev;
    }

    public void insert(int index, int value) {
        Node preNode = findNode(index - 1);
        if (preNode == null)
            throw illegalIndex(index);
        Node nextNode = preNode.next;
        Node node = new Node(preNode, value, nextNode);
        preNode.next = node;
        nextNode.prev = node;
    }

    /**
     * 按照索引删除节点
     *
     * @param index
     */
    public void remove(int index) {
        Node preNode = findNode(index - 1);
        if (preNode == null)
            throw illegalIndex(index);
        Node node = preNode.next;
        if (node == tail) {
            throw illegalIndex(index);
        }
        Node nextNode = node.next;
        preNode.next = nextNode;
        nextNode.prev = preNode;

    }

    private IllegalArgumentException illegalIndex(int index) {
        return new IllegalArgumentException(String.format("参数[%d]非法", index));
    }

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            Node p = head;

            @Override
            public boolean hasNext() {
                return p.next != tail;
            }

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


    static class Node {
        Node prev;
        Integer value;
        Node next;

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

3.动态数组

public class DynamicArray implements Iterable<Integer> {
    private int size = 0; //逻辑大小
    private int capacity = 10; //容量
    private int[] array = new int[]{}; //动态数组

    public void add(int index, int num) {
        checkArray();
        if (index >= 0 && index < size)
            System.arraycopy(array, index, array, size, size - index);
        array[index] = num;
        size++;
    }

    private void checkArray() {
        if (size == 0)
            array = new int[capacity];
        if (capacity == size) {
            capacity += capacity >>> 1;
            int[] t = new int[capacity];
            System.arraycopy(array, 0, t, 0, size);
            array = t;
        }
    }

    public int[] copyElement() {
        capacity = capacity + (capacity >>> 1);
        int[] t = new int[capacity];
        System.arraycopy(array, 0, t, 0, array.length);
        return t;
    }

    public int get(int index) {
        return array[index];
    }

    public int del(int index) {
        int removed = array[index];
        if (index < size - 1)
            System.arraycopy(array, index + 1, array, index, size - index - 1);
        size--;
        return removed;
    }

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

    @Override
    public String toString() {
        return "DynamicArray{" +
                "size=" + size +
                ", capacity=" + capacity +
                ", array=" + Arrays.toString(array) +
                '}';
    }
    public IntStream stream(){
        return IntStream.of(Arrays.copyOfRange(array,0,size));
    }

    @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++];
            }
        };
    }
}

4.递归

1.带缓存的斐波那契(时间复杂度O(n^2))

public class Fibonacci {

    public int fun(int i) {
        int[] cache = new int[i + 1];
        Arrays.fill(cache, -1);
        cache[0] = 0;
        cache[1] = 1;
        return f(i, cache);
    }

    private int f(int i, int[] cache) {
        if (cache[i] != -1) {
            return cache[i];
        }
        cache[i] = f(i - 1, cache) + f(i - 2, cache);
        return cache[i];
    }

    @Test
    public void test1() {
        System.out.println(fun(12));
    }
}

2.逆序输出字符串

public class MyStringPrint {
    public static void main(String[] args) {
        String s="abcd";
        f(0,s);
    }

    public static void f(Integer n, String str) {
        if (n == str.length())
            return;
        f(n + 1, str);
        System.out.println(str.charAt(n));
    }
}

5.排序算法

1.插入排序

public class InsertSort {
    //普通版
    public void sort1(int[] arr) {
        for (int low = 1; low < arr.length; low++) {
            int t = arr[low];
            int i = low - 1;
            while (i >= 0 && arr[i] > t) {
                arr[i + 1] = arr[i];
                i--;
            }
            if (arr[i + 1] != low)
                arr[i + 1] = t;
        }
    }

    //递归版
    public void sort2(int[] a, int low) {
        if (low == a.length) {
            return;
        }
        int t = a[low];
        int i = low - 1;
        while (i >= 0 && a[i] > t) {
            a[i + 1] = a[i];
            i--;
        }
        if (a[i + 1] != low)
            a[i + 1] = t;
        sort2(a, low + 1);
    }

    @Test
    public void test1() {
        int[] arr = new int[]{7, 12, 2, 0, 12, 12, 43, 42};
        sort1(arr);
        System.out.println(Arrays.toString(arr));
    }
}

2.冒泡排序

public class BubbleSort {
    //普通版
    public void sort1(int[] a) {
        int t;
        for (int i = 0; i < a.length - 1; i++) {
            for (int j = 0; j < a.length - i - 1; j++) {
                if (a[j] > a[j + 1]) {
                    t = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = t;
                }
            }
        }
    }

    //递归版
    public void sort2(int[] a, int j) {
        if (j < 1) {
            return;
        } else {
            int t, x = 0;
            for (int i = 0; i < j; i++) {
                if (a[i] > a[i + 1]) {
                    t = a[i];
                    a[i] = a[i + 1];
                    a[i + 1] = t;
                    x = i;
                }
            }
            sort2(a, x);
        }
    }

    @Test
    public void test1() {
        int[] arr = new int[]{7, 12, 2, 0, 12, 12, 42, 43};
        sort1(arr);
        System.out.println(Arrays.toString(arr));

    }
}