Data Structures - Basics

The composition of the data structure

data structure

The list of features and advantages and disadvantages of each structure is very easy to forget even if it is memorized. It is better to analyze the advantages and disadvantages when understanding the functional implementation needs.

Logical structure:

线性结构 -> 集合(无逻辑关系  只是放一块)
     线性结构(线性表 一对一):队列  栈  一维数组 给予特定特点 方便实现特定功能
非线性结构
      树(一对多)
      图(多对多)
      二位数组

Memory structure:

顺序存储: 连续内存存储
链表存储:额外需要存储附近节点的引用
索引存储:额外需要存储索引表,索引表的存储又可以分树/哈希之类
散列存储:额外需要哈希算法

From an object-oriented point of view, it is actually not related to the memory structure, so although a logical structure can have multiple memory representations, for example, a sequential list/linked list is composed of a linear list + sequential storage/linked list storage, but the data we often talk about structure or logical structure

 package dataStructure;


import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

/**
 * 参照linkedlist 
 * 链表  链式存储-- 查找取下标也是需要遍历  删除和新增和方便  可查看LinkedList双向链表
 *   维护头结点和链表大小  一直往下next
 * 哨兵 即守门的  在头和尾加哨兵 则能减少空值判断 则整体对外没有什么区别
 * head.pre = 哨兵
 * last.next = 哨兵
 *
 * Created by EX on 2018/4/12.
 */
public class MyLink implements MyDataStr {

    MyNode head;
    int size;

    public static void main(String[] args) {
        MyLink myLink = new MyLink();
        myLink.add("ss1");
        myLink.add("2");
        myLink.add("ss3");

        myLink.delete();
        myLink.add("ss4");

        System.out.println(myLink.find("2"));
        System.out.println(myLink.size());
        myLink.display();
    }

    public void add(Object data) {
        MyNode newNode = new MyNode(data);
        if (head == null) {
            head = newNode;
        } else {
            newNode.next = head;
            head = newNode;
        }
        size++;
    }

    public Object delete() {
        Object data = head.data;
        head = head.next;
        size--;
        return data;
    }

    public void delete(int i) {

    }

    public void delete(Object value) {
        //删除指定节点  只需要改变该节点的前后节点的指向


    }

    public Object get(int i) {
        MyNode x = head;

        for (int j = 0; j < i; j++) {
            x = head.next;
        }

        return x.data;
    }

    public MyNode find(Object value) {
        //遍历节点
        MyNode current = head;

        while (!current.data.equals(value)) {
            current = current.next;

            if (current == null) {
                break;
            }
        }
        return current;
    }

    public int search(Object value) {
        return 0;
    }

    public void display() {
        MyNode x = head;
        for (int j = 0; j < size; j++) {
            System.out.println(x.data);
            x = x.next;
        }
    }

    public int size() {
        return size;
    }

    private class MyNode {
        Object data;
        MyNode next;

        public MyNode(Object data) {
            this.data = data;
        }

        @Override
        public String toString() {
            return ToStringBuilder.reflectionToString(this,ToStringStyle.JSON_STYLE);
        }
    }

}
package dataStructure;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

/**
 * 二叉树  维护root及其左右子树  以第一个内容为root 然后根据大小比较后往子树中添加
 * on 2018/4/12.
 */
public class MyTree {

    public static void main(String[] args) {
        MyTree myTree = new MyTree();
        myTree.insert("d");
        myTree.insert("a");
        myTree.insert("z");
        myTree.insert("y");
        myTree.insert("b");

        myTree.display();
    }


    Node root;

    public Node find(Object data) {
        if (root == null) {
            return null;
        }

        Node current = root;

        while (current != null) {
            if (data.hashCode() > current.data.hashCode()) {
                current = root.right;
            } else if (data.hashCode() < current.data.hashCode()) {
                current = root.left;
            } else {
                return current;
            }
        }

        return null;
    }


    public boolean insert(Object data) {
        Node newNode = new Node(data);

        if (root == null) {
            root = newNode;
            return true;
        }

        Node current = root;
        Node parentNode = null;
        while (current != null) {
            parentNode = current;
            if (data.hashCode() > current.data.hashCode()) {
                /*current = current.right;
                if(current == null){
                    current = newNode;
                    return true;
                }*/
                current = current.right;
                if (current == null) {//左子节点为空,直接将新值插入到该节点
                    parentNode.right = newNode;
                    return true;
                }
            } else {
                /*Node right = current.left;
                if(right == null){
                    right = newNode;
                }else{
                    current = right;
                }
                return true;*/

                current = current.left;
                if (current == null) {//右子节点为空,直接将新值插入到该节点
                    parentNode.left = newNode;
                    return true;
                }
            }
        }

        return false;
    }

    public void display() {
        System.out.println("root:" + root);
        midDisplay(root);
    }

    private void midDisplay(Node node) {
        if (node != null) {
            midDisplay(node.left);
            System.out.println(node);
            midDisplay(node.right);
        }
    }


    public class Node {
        Object data;
        Node left;
        Node right;

        public Node(Object data, Node left, Node right) {
            this.data = data;
            this.left = left;
            this.right = right;
        }

        public Node(Object data) {
            this.data = data;
        }

        public Node() {
        }

        @Override
        public String toString() {
            return (String) data;
        }
    }
}

hashtable hashCode determines the position in the array, equals determines whether it needs to be placed in the linked list under the array

package dataStructure;

import javafx.util.Duration;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.commons.lang3.time.DateUtils;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.util.Hashtable;

/**
 * 散列  参照hashTable源码
 * Created by EX-ZHOUXIAOWEI004 on 2018/4/12.
 */
public class MyHashTable<K,V>{
    private Entry<?,?>[]  table;//存放数据
    private transient int count;
    private int threshold;//容量
    private float loadFactor;//负载因子
    private transient int modCount = 0;//元素个数

    public static void main(String[] args) {
        new MyHashTable<String,String>(10,1);

    }
    public MyHashTable(int initialCapacity, float loadFactor) {
        //参数检测忽略掉了 直接初始化

        this.loadFactor = loadFactor;
//        table = new Entry<?,?>[initialCapacity];
        threshold = (int)Math.min(initialCapacity * loadFactor, Integer.MAX_VALUE - 8 + 1);
    }


    public synchronized V put(K key, V value){
        Entry<?,?> tab[] = table;//成员变量 赋值给局部变量  成员变量存在堆,局部存在栈  栈的数据操作更快
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;//在table中的下标  或者叫位桶
        Entry<K,V> entry = (Entry<K,V>)tab[index];//取到当前位桶的entry   而ertry是一个链表

        //遍历这个entry链表 确认否存在这个key
        for (;entry != null; entry = entry.next){
            if (key.equals(entry.key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }

        //如果不存在这个key
        addEntry(hash,key,value,index);


        return value;
    }

    private void addEntry(int hash, K key, V value, int index) {
        //确认是否需要扩容

        modCount++;
        Entry<?,?> tab[] = table;


        //取出index下的entry,然后新建一个entry指向原有的entry
        Entry<K, V> oldEntry = (Entry<K, V>) tab[index];
        Entry<K, V> newEntry = new Entry<K, V>(hash, key, value, oldEntry);//新的entry指向原有的entry
        tab[index] = newEntry;

        count++;


    }


    private class Entry<K,V>{
        final int hash;
        final K key;
        V value;
        Entry<K,V> next;

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

        @Override
        public String toString() {
            return ToStringBuilder.reflectionToString(this, ToStringStyle.SIMPLE_STYLE);
        }
    }
}




data structure in java

Common structure

  1. Collection
    List

    • ArrayList array implementation
    • Vector is actually the synchronized version of the array implementation
public synchronized E remove(int index) {
        modCount++;
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
        E oldValue = elementData(index);

        int numMoved = elementCount - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--elementCount] = null; // Let gc do its work

        return oldValue;
    }

LinkedList doubly linked list maintains head and tail Node first;/Node last

private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

Set
HashSet internally maintains a HashMap and uses the characteristics of the key to ensure uniqueness

public HashSet(Collection<? extends E> c) {
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
    }

TreeSet also maintains a TreeMap inside

Map

 HashMap 数组+链表(+红黑树java8)
 TreeMap 红黑树 

Queen queue

ArrayBlockingQueue
LinkedBlockingQueue

thread safe structure

The Collections collection tool also provides the inner class SynchronizedList/SynchronizedMap. Its essence is to use the decorator pattern to add a synchronized pessimistic lock to the original method.

 static class SynchronizedList<E>
        extends SynchronizedCollection<E>
        implements List<E> {
      final List<E> list;
      public void add(int index, E element) {
            synchronized (mutex) {list.add(index, element);}
        }
        public E remove(int index) {
            synchronized (mutex) {return list.remove(index);}
        }
}

After 1.5, the java.util.concurrent concurrent package provides various list/maps that are thread-safe. It uses the CAS optimistic lock
. When put, compareAndSwapObject will be called. This is a native method, and get will not call

    static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
                                        Node<K,V> c, Node<K,V> v) {
        return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
    }

[Dynamic visualization of data structures]( https://visualgo.net/zh

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324682234&siteId=291194637