【数据结构】常用数据结构及其手写实现

1,常用数据结构

List:有序的线性存储结构;

Set:元素不重复的存储结构,JDK有基于HashMap和TreeMap分别实现无序和有序Set;

Queue:先进先出的存储结构;

Stack:先进后出的存储结构;

Map:Key-Value存储结构;

Tree:树状存储结构;本文不展开分析此类

2,ArrayList和LinkedList简单实现

(1)ArrayList核心思想是利用数组,动态扩展大小;最大为2^32。通过数据实现,查找/修改时间复杂度为O(1)是删除/增加为O(n)

package _数据结构._List;


import java.util.*;

/**
 * @program: suanfa_by_java
 * @author: 一树
 * @data: 2020/11/14 19:21
 */

//实现可迭代接口
public class MyArrayList<T> implements Iterable<T> {

    private static final int DEFAULT_CAPACITY = 10;

    private int size;

    private T[] Items;

    public MyArrayList() {
        doInit();
        ensureCapacity(DEFAULT_CAPACITY);
    }

    public MyArrayList(int initCapacity) {
        doInit();
        ensureCapacity(initCapacity);
    }

    public MyArrayList(Collection<? extends T> c) {
        doInit();
        ensureCapacity(DEFAULT_CAPACITY);
        for (T t : c) {
            this.add(t);
        }
    }

    @SuppressWarnings("unchecked")
    public void clear() {
        doInit();
        Items = (T[]) new Object[DEFAULT_CAPACITY];
    }

    public int size() {
        return size;
    }

    private void doInit() {
        this.size = 0;
    }

    @SuppressWarnings("unchecked")
    private void ensureCapacity(int newCapacity) {
        if (newCapacity < 0) {
            throw new IllegalArgumentException("newCapacity < 0");
        }
        if (newCapacity < size) return;
        T[] old = Items;
        Items = (T[]) new Object[newCapacity];
        for (int i = 0; i < size(); i++) {
            Items[i] = old[i];
        }

    }

    public T set(int index, T value) {
        checkIndex(index);
        T old = Items[index];
        Items[index] = value;
        return old;
    }

    public T get(int index) {
        checkIndex(index);
        return Items[index];
    }


    public void add(T value) {

        if (size() == Items.length) {
            //扩容
            ensureCapacity(2 * size() + 1);
        }

        Items[size()] = value;
        size++;
    }
   
    //消费者模式,只可读不可写的泛型限定
    public void addAll(Collection<? extends T> c) {
        for (T t : c) {
            this.add(t);
        }
    }


    public void remove(int index) {
        checkIndex(index);
        for (int i = index; i < size() - 1; i++) {
            Items[i] = Items[i + 1];
        }
        size--;
    }

    private void checkIndex(int index) {
        if (index < 0 || index >= size) {
            throw new ArrayIndexOutOfBoundsException();
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0; i < size; i++) {
            sb.append(Items[i]);
            sb.append(',');
        }

        sb.delete(sb.length() - 1, sb.length());
        sb.append(']');
        return sb.toString();
    }

    @SuppressWarnings("unchecked")
    public void sort(Comparator<? super T> c) {
        T[] a = (T[]) new Object[size];
        for (int i = 0; i < size; i++) {
            a[i] = Items[i];
        }
        Arrays.sort(a, c);
        for (int i = 0; i < size; i++) {
            Items[i] = a[i];
        }
    }

    @Override
    public Iterator<T> iterator() {
        return new ArrayListIterator();
    }
    
    // 具体可迭代的实现者接口
    private class ArrayListIterator implements java.util.Iterator<T> {

        private int current = 0;

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

        @Override
        public T next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            return (T) Items[current++];
        }

        @Override
        public void remove() {
            MyArrayList.this.remove(--current);
        }

    }
}

(2)LinkedList,利用链表实现。查找/修改时间复杂度为O(n),删除/增加复杂度为O(1);

package _数据结构._List;

import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * @program: suanfa_by_java
 * @author: 一树
 * @data: 2020/11/15 10:34
 */
public class MyLinkedList<T> implements Iterable<T>{

    private int size;
    private Node<T> beginMarker;
    private Node<T> endMarker;

    public MyLinkedList() {
        doInit();
    }

    public MyLinkedList(Collection<? extends T> c) {
        doInit();
        for (T t : c) {
            add(t);
        }
    }

    private void doInit() {
        size = 0;
    }

    public void addAll(Collection<? extends T> others) {
        for (T other : others) {
            add(other);
        }
    }

    //双链表
    private class Node<T> {
        T value;
        Node<T> next;
        Node<T> prefix;

        public Node(T value) {
            this.value = value;
        }
    }

    private Node<T> getNode(int index) {
        checkIndex(index);
        Node<T> p;
        int cnt = 0;
        int limit = size - 1;

        if (index <= limit / 2) {
            p = beginMarker;
            while (cnt < index) {
                cnt++;
                p = p.next;
            }
            return p;

        } else {
            p = endMarker;
            while (cnt < index) {
                cnt++;
                p = p.prefix;
            }
            return p;
        }
    }


    private boolean deleteNode(int index) {
        checkIndex(index);

        if (index > 0 && index < size - 1) {
            Node<T> node = getNode(index);
            Node<T> prefix = node.prefix;
            Node<T> next = node.next;
            prefix.next = next;
            next.prefix = prefix;
            node.next = null;
            node.prefix = null;
            return true;
        }

        if (index == 0) {
            Node<T> node = this.beginMarker;
            Node<T> next = node.next;
            next.prefix = null;
            beginMarker = next;
            node.next = null;
        }


        if (index == size - 1) {
            Node<T> node = this.endMarker;
            Node<T> prefix = node.prefix;
            prefix.next = null;
            node.prefix = null;
            endMarker = prefix;
            return true;
        }
        return false;
    }

    private boolean insertNode(int index, Node<T> node) {

        if (size == 0) {
            beginMarker = node;
            endMarker = node;
            return true;
        }

        if (index > 0 && index < size - 1) {
            Node<T> nextNode = getNode(index);
            Node<T> preNode = nextNode.prefix;
            preNode.next = node;
            node.prefix = preNode;
            nextNode.prefix = node;
            node.next = nextNode;
            return true;
        }

        if (index == 0) {
            beginMarker.prefix = node;
            node.next = beginMarker;
            beginMarker = node;
            return true;

        }

        if (index == size) {
            endMarker.next = node;
            node.prefix = endMarker;
            endMarker = node;
            return true;
        }

        return false;
    }

    private void checkIndex(int index) {
        if (index < 0 || index >= size)
            throw new ArrayIndexOutOfBoundsException();
    }


    public void add(T t) {
        this.insertNode(size, new Node<T>(t));
        size++;
    }


    public void remove(int index) {
        this.deleteNode(index);
        size--;
    }

    public T get(int index) {
        return getNode(index).value;
    }

    public T set(int index, T newValue) {
        Node<T> node = getNode(index);
        T old = node.value;
        node.value = newValue;
        return old;
    }

    public int size() {
        return size;
    }


    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        Iterator<T> iterator = iterator();
        sb.append('[');
        while (iterator.hasNext()) {
            sb.append(iterator.next());
            sb.append(',');
        }
        sb.delete(sb.length() - 1, sb.length());
        sb.append(']');
        return sb.toString();
    }

    /**
     * 迭代器接口
     */
    @Override
    public Iterator<T> iterator() {
        return new LinkedListIterator();
    }


    private class LinkedListIterator implements java.util.Iterator<T> {
        Node<T> current = beginMarker;

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

        @Override
        public T next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }

            T nextItem = current.value;
            current = current.next;
            return nextItem;
        }

        @Override
        public void remove() {
            MyLinkedList.this.remove(MyLinkedList.this.size - 1);
        }
    }
}

3,HashMap简单实现

通过查看HashMap源码,可知核心有散列表、扩若阀值等;

判断两个元素是否相等,通过hash值和equal联合判断;

在JDK规范中,hash相等,equal不一定相等;

hash相等而equal不等就属于hash冲突,jdk采用链表解决hash冲突;即每个散列表中存储的元素都是一个双链表;

package _数据结构._Map;

import java.util.*;

/**
 * @program: suanfa_by_java
 * @author: 一树
 * @data: 2020/11/16 9:49
 */
public class MyHashMap<K, V> {

    private static final int DEFAULT_CAPACITY = 17;
    private static final float DEFAULT_LOAD = 0.75f;
    private static final int MAX_CAPACITY = (1 << 30) + 1;
    private int size;
    private int resizeCount;
    private Node<K, V>[] table;
    private int tableLength;
    private float load;


    @SuppressWarnings("unchecked")
    public MyHashMap(int capacity, float load) {
        this.tableLength = capacity;
        this.load = load;
        this.table = (Node<K, V>[]) new Node[capacity];
    }

    @SuppressWarnings("unchecked")
    public MyHashMap(int capacity) {
        this.tableLength = capacity;
        this.load = DEFAULT_LOAD;
        this.table = (Node<K, V>[]) new Node[capacity];
    }

    @SuppressWarnings("unchecked")
    public MyHashMap() {
        this.load = DEFAULT_LOAD;
        this.tableLength = DEFAULT_CAPACITY;
        this.table = (Node<K, V>[]) new Node[tableLength];
    }

    @SuppressWarnings("unchecked")
    public MyHashMap(Map<? extends K, ? extends V> map) {
        this.load = DEFAULT_LOAD;
        this.tableLength = DEFAULT_CAPACITY;
        this.table = (Node<K, V>[]) new Node[tableLength];
        for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
            K key = entry.getKey();
            V value = entry.getValue();
            put(key, value);
        }
    }

    /*扩容*/
    @SuppressWarnings("unchecked")
    private void resize() {
        int newCapacity = Math.min(MAX_CAPACITY, (tableLength << 1) + 1);
        Node<K, V>[] oldTable = this.table;
        this.table = (Node<K, V>[]) new Node[newCapacity];
        this.tableLength = newCapacity;
        //将oldItem中的数重新散列
        for (Node<K, V> p : oldTable) {
            while (p != null) {
                K key = p.getKey();
                V value = p.getValue();
                put(key, value);
                p = p.next;
            }
        }
    }


    public void put(K k, V v) {
        this.putVal(k, v, hash(k, tableLength), false);
    }

    public void putIfAbsent(K k, V v) {
        this.putVal(k, v, hash(k, tableLength), true);
    }

    private void putVal(K k, V v, int hash, boolean abSent) {
        Node<K, V> p = table[hash];
        Node<K, V> pre = null;
        while (p != null) {
            if (p.key.equals(k)) {
                if (!abSent) p.value = v;
                return;
            }
            pre = p;
            p = p.next;
        }
        p = new Node<>(hash, k, v, null);
        if (pre == null) {
            table[hash] = p;
            resizeCount++;//记录表被占用的数
        } else {
            pre.next = p;
        }
        size++;
        if (resizeCount >= load * tableLength) {
            resize();
        }
    }
    
    public int size() {
        return size;
    }

    public V get(K k) {
        Node<K, V> p = table[hash(k, tableLength)];

        while (p != null) {
            if (k.equals(p.key)) return p.value;
            p = p.next;
        }

        return null;
    }

    public void remove(K k) {
        int index = hash(k, tableLength);
        Node<K, V> p = table[index];
        Node<K, V> pre = null;
        while (p != null) {
            if (k.equals(p.key)) {
                Node<K, V> next = p.next;
                if (next != null && pre != null) {
                    pre.next = next;
                    p.next = null;
                    size--;
                    return;
                }

                if (next == null && pre != null) {
                    pre.next = null;
                    size--;
                    return;
                }

                if (pre == null) {
                    table[index] = null;
                    size--;
                    return;
                }
            }
            pre = p;
            p = p.next;
        }
    }


    public V set(K k, V v) {
        V old = get(k);
        put(k, v);
        return old;
    }

    public boolean containKey(K k) {
        return get(k) != null;
    }

    //散列函数
    private static int hash(Object key, int tableSize) {
        String h = key.toString();
        int hash = 0;
        for (int i = 0; i < h.length(); i++) {
            hash = 37 * hash + h.charAt(i);
        }
        hash %= tableSize;
        if (hash < 0)
            hash += tableSize;
        return hash;
    }


    /*>>>>>>>>>>>>>>>>>>>>>>>>>>class Node>>>>>>>>>>>>>>>>>>>>>>*/
    public static class Node<K, V> {
        int hash;
        K key;
        V value;
        Node<K, V> next;

        Node(int hash, K key, V value, Node<K, V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        public K getKey() {
            return key;
        }

        public V getValue() {
            return value;
        }

        public void setValue(V value) {
            this.value = value;
        }
    }


    /*>>>>>>>>>>>>>>>>>>>Iterator>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

    public Set<Node<K, V>> enterSet() {

        Set<Node<K, V>> entrySet = new HashSet<>();
        //将数据装入set中
        for (int i = 1; i < tableLength; i++) {
            if (table[i] != null) {
                Node<K, V> p = table[i];
                while (p != null) {
                    entrySet.add(p);
                    p = p.next;
                }
            }
        }
        return entrySet;
    }

    public Set<K> enterKey() {
        Set<K> entryKey = new HashSet<>();
        //将数据装入set中
        for (int i = 1; i < tableLength; i++) {
            if (table[i] != null) {
                Node<K, V> p = table[i];
                while (p != null) {
                    entryKey.add(p.key);
                    p = p.next;
                }
            }
        }
        return entryKey;
    }

    public Set<V> enterValue() {
        Set<V> entryValue = new HashSet<>();
        //将数据装入set中
        for (int i = 1; i < tableLength; i++) {
            if (table[i] != null) {
                Node<K, V> p = table[i];
                while (p != null) {
                    entryValue.add(p.value);
                    p = p.next;
                }
            }
        }
        return entryValue;
    }

}

4,Queue简单实现

先进先出的数据结构,采用链表简单实现;

package _数据结构._Queue;

import java.util.EmptyStackException;

/**
 * @program: suanfa_by_java
 * @author: 一树
 * @data: 2020/11/15 15:10
 */
public class LinkedQueue<T> {

    private Node<T> first;
    private Node<T> end;
    private int size;

    private class Node<T> {
        T val;
        Node<T> next;
        Node<T> pre;

        Node() {
        }

        Node(T val) {
            this.val = val;
        }
    }

    public LinkedQueue() {
        doInit();
    }

    private void doInit() {
        size = 0;
        first = new Node<>();
        end = new Node<>();
        first.next = end;
        end.pre = first;
    }

    public boolean offer(T val) {
        Node<T> node = new Node<>(val);
        Node<T> pre = end.pre;
        pre.next = node;
        node.pre = pre;
        node.next = end;
        end.pre = node;
        size++;
        return true;
    }

    public T poll() {
        if (size == 0) {
            throw new EmptyStackException();
        }

        Node<T> t = first.next;
        T val = t.val;
        t.next.pre = first;
        first.next = t.next;
        t.next = null;
        t.pre = null;
        size--;
        return val;
    }

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

    public T peek() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        return first.next.val;
    }
}

5,Stack简单实现

先进后出的数据结构,有Array和Link两种实现

(1)ArrayStack

package _数据结构._Stack;

import java.util.Collection;
import java.util.EmptyStackException;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * @program: suanfa_by_java
 * @author: 一树
 * @data: 2020/11/15 13:47
 */
public class ArrayStack<T> implements Iterable<T> {

    private static final int DEFAULT_CAPACITY = 10;

    private int size;

    private T[] Items;


    public ArrayStack() {
        doInit();
        ensureCapacity(DEFAULT_CAPACITY);
    }

    public ArrayStack(int initCapacity) {
        doInit();
        ensureCapacity(initCapacity);
    }

    public ArrayStack(Collection<? extends T> c) {
        doInit();
        ensureCapacity(DEFAULT_CAPACITY);
        for (T t : c) {
            this.push(t);
        }
    }

    @SuppressWarnings("unchecked")
    public void clear() {
        doInit();
        Items = (T[]) new Object[DEFAULT_CAPACITY];
    }

    public int size() {
        return size;
    }

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

    private void doInit() {
        this.size = 0;
    }

    @SuppressWarnings("unchecked")
    private void ensureCapacity(int newCapacity) {
        if (newCapacity < 0) {
           throw new IllegalArgumentException("newCapacity < 0");
        }
        if (newCapacity < size) return;
        T[] old = Items;
        Items = (T[]) new Object[newCapacity];
        for (int i = 0; i < size(); i++) {
            Items[i] = old[i];
        }

    }

    public T set(int index, T value) {
        checkIndex(index);
        T old = Items[index];
        Items[index] = value;
        return old;
    }

    public T peek() {
        return Items[size - 1];
    }


    public void push(T value) {

        if (size() == Items.length) {
            //扩容
            ensureCapacity(2 * size() + 1);
        }

        Items[size()] = value;
        size++;
    }


    public T pop() {
        if (size == 0)
            throw new EmptyStackException();
        return Items[--size];
    }

    private void checkIndex(int index) {
        if (index < 0 || index >= size) {
            throw new ArrayIndexOutOfBoundsException();
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0; i < size; i++) {
            sb.append(Items[i]);
            sb.append(',');
        }

        sb.delete(sb.length() - 1, sb.length());
        sb.append(']');
        return sb.toString();
    }

    @Override
    public Iterator<T> iterator() {
        return new ArrayStackIterator();
    }

    private class ArrayStackIterator implements java.util.Iterator<T> {

        private int current = 0;

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

        @Override
        public T next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            return (T) Items[current++];
        }

        @Override
        public void remove() {
            ArrayStack.this.pop();
        }
    }
}


(2)LinkedStack

package _数据结构._Stack;

import java.util.Collection;
import java.util.EmptyStackException;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * @program: suanfa_by_java
 * @author: 一树
 * @data: 2020/11/15 14:18
 */
public class LinkedStack<T> implements Iterable<T> {

    private int size;
    private Node<T> beginMarker;
    private Node<T> endMarker;

    public LinkedStack() {
        doInit();
    }

    public LinkedStack(Collection<? extends T> c) {
        doInit();
        for (T t : c) {
            push(t);
        }
    }

    private void doInit() {
        size = 0;
    }

    public void pushAll(Collection<? extends T> others) {
        for (T other : others) {
            push(other);
        }
    }

    //内部类
    private class Node<T> {
        T value;
        Node<T> next;
        Node<T> prefix;

        public Node(T value) {
            this.value = value;
        }
    }

    private Node<T> getNode(int index) {
        checkIndex(index);
        Node<T> p;
        int cnt = 0;
        int limit = size - 1;

        if (index <= limit / 2) {
            p = beginMarker;
            while (cnt < index) {
                cnt++;
                p = p.next;
            }
            return p;

        } else {
            p = endMarker;
            while (cnt < index) {
                cnt++;
                p = p.prefix;
            }
            return p;
        }
    }


    private T deleteEndNode() {

        Node<T> node = this.endMarker;
        Node<T> prefix = node.prefix;
        T value = node.value;
        if (prefix != null) prefix.next = null;
        node.prefix = null;
        endMarker = prefix;
        return value;

    }

    private boolean insertNode(int index, Node<T> node) {

        if (size == 0) {
            beginMarker = node;
            endMarker = node;
            return true;
        }

        if (index > 0 && index < size - 1) {
            Node<T> nextNode = getNode(index);
            Node<T> preNode = nextNode.prefix;
            preNode.next = node;
            node.prefix = preNode;
            nextNode.prefix = node;
            node.next = nextNode;
            return true;
        }

        if (index == 0) {
            beginMarker.prefix = node;
            node.next = beginMarker;
            beginMarker = node;
            return true;

        }

        if (index == size) {
            endMarker.next = node;
            node.prefix = endMarker;
            endMarker = node;
            return true;
        }

        return false;
    }

    private void checkIndex(int index) {
        if (index < 0 || index >= size)
            throw new ArrayIndexOutOfBoundsException();
    }

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

    public void push(T val) {
        this.insertNode(size, new Node<T>(val));
        size++;
    }

    public T pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        T value = this.deleteEndNode();
        size--;
        return value;
    }

    public T peek() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        return endMarker.value;
    }

    public int size() {
        return size;
    }


    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        Iterator<T> iterator = iterator();
        sb.append('[');
        while (iterator.hasNext()) {
            sb.append(iterator.next());
            sb.append(',');
        }
        sb.delete(sb.length() - 1, sb.length());
        sb.append(']');
        return sb.toString();
    }

    /**
     * 迭代器接口
     */
    @Override
    public Iterator<T> iterator() {
        return new LinkedListIterator();
    }


    private class LinkedListIterator implements java.util.Iterator<T> {
        Node<T> current = beginMarker;

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

        @Override
        public T next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }

            T nextItem = current.value;
            current = current.next;
            return nextItem;
        }

        @Override
        public void remove() {
            LinkedStack.this.pop();
        }
    }
}

6,HashSet

采用上述封装的MyHashMap实现HashSet,达到去重效果

package _数据结构._Set;

import _数据结构._Map.MyHashMap;

import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

/**
 * @program: suanfa_by_java
 * @author: 一树
 * @data: 2020/11/16 19:50
 */
public class MyHashSet<T> implements Iterable<T> {
    private final Object P = new Object();
    private int size;
    private MyHashMap<T, Object> map;

    public MyHashSet() {
        map = new MyHashMap<>();
        size = 0;
    }

    public MyHashSet(Collection<? extends T> c) {
        map = new MyHashMap<>();
        size = 0;
        for (T t : c) {
            add(t);
        }
    }

    public void add(T t) {
        if (!map.containKey(t)) {
            map.put(t, P);
            size++;
        }
    }

    public void remove(T t) {
        if (map.containKey(t)) {
            map.remove(t);
        }
    }

    public int size() {
        return size;
    }

    public boolean contain(T t) {
        return map.containKey(t);
    }


    @Override
    public Iterator<T> iterator() {
        return map.enterKey().iterator();
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值