zoukankan      html  css  js  c++  java
  • 常用数据结构-线性表及Java 动态数组 深究

    【Java心得总结六】Java容器中——Collection在前面自己总结的一篇博文中对Collection的框架结构做了整理,这里深究一下Java中list的实现方式

    1.动态数组

    In computer science, a dynamic arraygrowable arrayresizable arraydynamic tablemutable array, or array list is a random access, variable-size list data structure that allows elements to be added or removed. It is supplied with standard libraries in many modern mainstream programming languages.

    A dynamic array is not the same thing as a dynamically allocated array, which is a fixed-size arraywhose size is fixed when the array is allocated, although a dynamic array may use such a fixed-size array as a back end.

    ——维基百科

    我们可以看出动态数组在动态分配数组(固定大小数组)的基础上实现的可随机存取大小可变的一种数据结构

    2.Java中ArrayList实现

    我截取了部分ArrayList的Java实现:

    代码段1

      1 public class ArrayList<E> extends AbstractList<E>
      2         implements List<E>, RandomAccess, Cloneable, java.io.Serializable
      3 {
      4     private transient Object[] elementData;
      5     
      6     private int size;
      7     
      8     public ArrayList(int initialCapacity) {
      9         super();
     10         if (initialCapacity < 0)
     11             throw new IllegalArgumentException("Illegal Capacity: "+
     12                                                initialCapacity);
     13         this.elementData = new Object[initialCapacity];
     14     }
     15 
     16     public ArrayList() {
     17         this(10);
     18     }
     19     
     20     public ArrayList(Collection<? extends E> c) {
     21         elementData = c.toArray();
     22         size = elementData.length;
     23         // c.toArray might (incorrectly) not return Object[] (see 6260652)
     24         if (elementData.getClass() != Object[].class)
     25             elementData = Arrays.copyOf(elementData, size, Object[].class);
     26     }
     27     
     28     private void grow(int minCapacity) {
     29         // overflow-conscious code
     30         int oldCapacity = elementData.length;
     31         int newCapacity = oldCapacity + (oldCapacity >> 1);
     32         if (newCapacity - minCapacity < 0)
     33             newCapacity = minCapacity;
     34         if (newCapacity - MAX_ARRAY_SIZE > 0)
     35             newCapacity = hugeCapacity(minCapacity);
     36         // minCapacity is usually close to size, so this is a win:
     37         elementData = Arrays.copyOf(elementData, newCapacity);
     38     }
     39     
     40     private static int hugeCapacity(int minCapacity) {
     41         if (minCapacity < 0) // overflow
     42             throw new OutOfMemoryError();
     43         return (minCapacity > MAX_ARRAY_SIZE) ?
     44             Integer.MAX_VALUE :
     45             MAX_ARRAY_SIZE;
     46     }
     47     
     48     /* 增加元素 */
     49     public boolean add(E e) {
     50         ensureCapacityInternal(size + 1);  // Increments modCount!!
     51         elementData[size++] = e;
     52         return true;
     53     }
     54 
     55     public void add(int index, E element) {
     56         rangeCheckForAdd(index);
     57 
     58         ensureCapacityInternal(size + 1);  // Increments modCount!!
     59         System.arraycopy(elementData, index, elementData, index + 1,
     60                          size - index);
     61         elementData[index] = element;
     62         size++;
     63     }
     64     
     65     private void rangeCheckForAdd(int index) {
     66         if (index > size || index < 0)
     67             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
     68     }
     69     
     70     /* 删除元素 */
     71     public E remove(int index) {
     72         rangeCheck(index);
     73 
     74         modCount++;
     75         E oldValue = elementData(index);
     76 
     77         int numMoved = size - index - 1;
     78         if (numMoved > 0)
     79             System.arraycopy(elementData, index+1, elementData, index,
     80                              numMoved);
     81         elementData[--size] = null; // Let gc do its work
     82 
     83         return oldValue;
     84     }
     85     
     86     public boolean remove(Object o) {
     87         if (o == null) {
     88             for (int index = 0; index < size; index++)
     89                 if (elementData[index] == null) {
     90                     fastRemove(index);
     91                     return true;
     92                 }
     93         } else {
     94             for (int index = 0; index < size; index++)
     95                 if (o.equals(elementData[index])) {
     96                     fastRemove(index);
     97                     return true;
     98                 }
     99         }
    100         return false;
    101     }
    102     
    103     private void fastRemove(int index) {
    104         modCount++;
    105         int numMoved = size - index - 1;
    106         if (numMoved > 0)
    107             System.arraycopy(elementData, index+1, elementData, index,
    108                              numMoved);
    109         elementData[--size] = null; // Let gc do its work
    110     }
    111     
    112     /* 查找元素 */
    113     public E get(int index) {
    114         rangeCheck(index);
    115 
    116         return elementData(index);
    117     }
    118     
    119     public int indexOf(Object o) {
    120         if (o == null) {
    121             for (int i = 0; i < size; i++)
    122                 if (elementData[i]==null)
    123                     return i;
    124         } else {
    125             for (int i = 0; i < size; i++)
    126                 if (o.equals(elementData[i]))
    127                     return i;
    128         }
    129         return -1;
    130     }
    131     
    132     public boolean contains(Object o) {
    133         return indexOf(o) >= 0;
    134     }
    135     
    136     private void rangeCheck(int index) {
    137         if (index >= size)
    138             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    139     }
    140     
    141     /* 修改元素 */
    142     public E set(int index, E element) {
    143         rangeCheck(index);
    144 
    145         E oldValue = elementData(index);
    146         elementData[index] = element;
    147         return oldValue;
    148     }
    149 }

    代码段2

    1 public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    2         T[] copy = ((Object)newType == (Object)Object[].class)
    3             ? (T[]) new Object[newLength]
    4             : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    5         System.arraycopy(original, 0, copy, 0,
    6                          Math.min(original.length, newLength));
    7         return copy;
    8     }
    • 代码4行,可以看出Java利用了一个Object数组来支持动态数组ArrayList的存取,Object[]的初始大小可以利用构造函数来进行设置
    • 在代码28行,可以看出当Object数组不够用的时候,Java会利用grow函数对原有数组进行扩展。查看Java Arrays类会找到copyOf静态方法,会发现Java会新开辟一段更大的存储空间(newLength),然后再将原有数组的数据全部复制到新的数组中,并返回新的引用。之后grow会将elementData指向新的数组。
    • 而接下来我按照增删查改的顺序对Java中的函数进行了列举,基本就是普通的动态数组操作,就不一一说明。

    3.Java中LinkedList实现

    Java中LinkedList就是用双向链表来实现的,我截取了部分代码:

    代码段1:

      1 public class LinkedList<E>
      2     extends AbstractSequentialList<E>
      3     implements List<E>, Deque<E>, Cloneable, java.io.Serializable
      4 {
      5     transient int size = 0;
      6 
      7     transient Node<E> first;
      8 
      9     transient Node<E> last;
     10 
     11     public LinkedList() {
     12     }
     13 
     14     public LinkedList(Collection<? extends E> c) {
     15         this();
     16         addAll(c);
     17     }
     18     /* 链表基本操作 */
     19     private void linkFirst(E e) {
     20         final Node<E> f = first;
     21         final Node<E> newNode = new Node<>(null, e, f);
     22         first = newNode;
     23         if (f == null)
     24             last = newNode;
     25         else
     26             f.prev = newNode;
     27         size++;
     28         modCount++;
     29     }
     30 
     31     void linkLast(E e) {
     32         final Node<E> l = last;
     33         final Node<E> newNode = new Node<>(l, e, null);
     34         last = newNode;
     35         if (l == null)
     36             first = newNode;
     37         else
     38             l.next = newNode;
     39         size++;
     40         modCount++;
     41     }
     42     
     43     void linkBefore(E e, Node<E> succ) {
     44         // assert succ != null;
     45         final Node<E> pred = succ.prev;
     46         final Node<E> newNode = new Node<>(pred, e, succ);
     47         succ.prev = newNode;
     48         if (pred == null)
     49             first = newNode;
     50         else
     51             pred.next = newNode;
     52         size++;
     53         modCount++;
     54     }
     55     
     56     private E unlinkFirst(Node<E> f) {
     57         // assert f == first && f != null;
     58         final E element = f.item;
     59         final Node<E> next = f.next;
     60         f.item = null;
     61         f.next = null; // help GC
     62         first = next;
     63         if (next == null)
     64             last = null;
     65         else
     66             next.prev = null;
     67         size--;
     68         modCount++;
     69         return element;
     70     }
     71     
     72     private E unlinkLast(Node<E> l) {
     73         // assert l == last && l != null;
     74         final E element = l.item;
     75         final Node<E> prev = l.prev;
     76         l.item = null;
     77         l.prev = null; // help GC
     78         last = prev;
     79         if (prev == null)
     80             first = null;
     81         else
     82             prev.next = null;
     83         size--;
     84         modCount++;
     85         return element;
     86     }
     87 
     88     E unlink(Node<E> x) {
     89         // assert x != null;
     90         final E element = x.item;
     91         final Node<E> next = x.next;
     92         final Node<E> prev = x.prev;
     93 
     94         if (prev == null) {
     95             first = next;
     96         } else {
     97             prev.next = next;
     98             x.prev = null;
     99         }
    100 
    101         if (next == null) {
    102             last = prev;
    103         } else {
    104             next.prev = prev;
    105             x.next = null;
    106         }
    107 
    108         x.item = null;
    109         size--;
    110         modCount++;
    111         return element;
    112     }
    113     
    114     /* 查找操作 */
    115     public int indexOf(Object o) {
    116         int index = 0;
    117         if (o == null) {
    118             for (Node<E> x = first; x != null; x = x.next) {
    119                 if (x.item == null)
    120                     return index;
    121                 index++;
    122             }
    123         } else {
    124             for (Node<E> x = first; x != null; x = x.next) {
    125                 if (o.equals(x.item))
    126                     return index;
    127                 index++;
    128             }
    129         }
    130         return -1;
    131     }
    132     
    133     public int lastIndexOf(Object o) {
    134         int index = size;
    135         if (o == null) {
    136             for (Node<E> x = last; x != null; x = x.prev) {
    137                 index--;
    138                 if (x.item == null)
    139                     return index;
    140             }
    141         } else {
    142             for (Node<E> x = last; x != null; x = x.prev) {
    143                 index--;
    144                 if (o.equals(x.item))
    145                     return index;
    146             }
    147         }
    148         return -1;
    149     }
    150     
    151     /*添加操作*/
    152     public boolean addAll(int index, Collection<? extends E> c) {
    153         checkPositionIndex(index);
    154 
    155         Object[] a = c.toArray();
    156         int numNew = a.length;
    157         if (numNew == 0)
    158             return false;
    159 
    160         Node<E> pred, succ;
    161         if (index == size) {
    162             succ = null;
    163             pred = last;
    164         } else {
    165             succ = node(index);
    166             pred = succ.prev;
    167         }
    168 
    169         for (Object o : a) {
    170             @SuppressWarnings("unchecked") E e = (E) o;
    171             Node<E> newNode = new Node<>(pred, e, null);
    172             if (pred == null)
    173                 first = newNode;
    174             else
    175                 pred.next = newNode;
    176             pred = newNode;
    177         }
    178 
    179         if (succ == null) {
    180             last = pred;
    181         } else {
    182             pred.next = succ;
    183             succ.prev = pred;
    184         }
    185 
    186         size += numNew;
    187         modCount++;
    188         return true;
    189     }
    190     
    191     public boolean add(E e) {
    192         linkLast(e);
    193         return true;
    194     }
    195     
    196     /* 删除操作 */
    197     public E removeFirst() {
    198         final Node<E> f = first;
    199         if (f == null)
    200             throw new NoSuchElementException();
    201         return unlinkFirst(f);
    202     }
    203     
    204     public E removeLast() {
    205         final Node<E> l = last;
    206         if (l == null)
    207             throw new NoSuchElementException();
    208         return unlinkLast(l);
    209     }
    210     
    211     /* 修改操作 */
    212     public E set(int index, E element) {
    213         checkElementIndex(index);
    214         Node<E> x = node(index);
    215         E oldVal = x.item;
    216         x.item = element;
    217         return oldVal;
    218     }
    219 }

    代码段2:

     1 private static class Node<E> {
     2         E item;
     3         Node<E> next;
     4         Node<E> prev;
     5 
     6         Node(Node<E> prev, E element, Node<E> next) {
     7             this.item = element;
     8             this.next = next;
     9             this.prev = prev;
    10         }
    11     }
    • 代码段1的7行和9行,我们可以看到Java中LinkedList的实现就是我们所熟知的双向链表数据结构,并且声明了头指针和尾指针分别指向链表的头和尾
    • 每个节点的结构见代码段2,发现是基本的双向链表节点结构
    • 而从代码18行开始就是常规的链表操作,包括插入结点和删除结点的操作
    • 而之后的增删查改操作大都是利用基本的链表操作实现的
    • 另外,值得注意的是LinkedList在Java中还有一个特殊功效就是通过向上转型当做队列Queue来使用

      如下面这段代码

    Queue<Integer> queue = new LinkedList<Integer>();

      这里向上转型无非是将LinkedList限制为头尾读取。

    Java中的动态数组实现,比较简单,复习回顾下,做下记录^v^

  • 相关阅读:
    快排
    SQL实例
    14_可变字符串类和日期相关类
    13_String类的概述和使用
    c# json object Dictionary互转
    SQL Server 数据表给现有字段添加默认值或修改默认值
    SQL Server2008R2 死锁进程杀掉处理
    Sql Server 2008R2 查看SQL语句运行时间
    fatal: unable to access 'https://github.com/xxx': OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443
    idea出现了不能复制的问题
  • 原文地址:https://www.cnblogs.com/xlturing/p/4450495.html
Copyright © 2011-2022 走看看