数据结构(一)ArrayList & LinkedList

1. ArrayList VS LinkedList

1.1 ArrayList

  1. List 的可增长数组实现
  2. 优点:对 get 和 set 的调用花费常数时间
  3. 缺点:插入和删除开销昂贵

1.2 LinkedList

  1. List的双链表实现
  2. 优点:插入和删除开销小(若变动项位置已知,花费常数时间)
  3. 缺点:对 get 的调用开销昂贵

2. ArrayList 的简单实现

ArrayList实现

package chapter2.arrayList;

public class MyArrayList {
    private static final int CAPACITY = 10;
    private int size;
    private Object[] nodes;

    public MyArrayList() {
        size = 0;
        ensureCapacity(CAPACITY);   //初始化数组最大容量为10
    }

    /**
     * 确认数组容量是否足够,不够则扩充容量
     * 扩充容量开销高,应避免频繁扩容
     *
     * @param newCapacity 新容量
     */
    private void ensureCapacity(int newCapacity) {
        if (newCapacity < size) {
            return;
        }
        Object[] oldNodes = nodes;
        nodes = new Object[newCapacity];

        for (int i = 0; i < size; i++) {
            nodes[i] = oldNodes[i];
        }
    }

    /**
     * 得到数组大小
     *
     * @return size
     */
    public int size() {
        return size;
    }

    /**
     * 判断数组是否为空
     *
     * @return true or false
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 判断数组是否包含某个元素
     *
     * @param element 要判断的元素
     * @return true or false
     */
    public boolean contains(Object element) {
        for (int i = 0; i < size; i++) {
            if (element.equals(nodes[i]))
                return true;
        }
        return false;
    }

    /**
     * 在数组末尾插入元素
     *
     * @param element 要插入的元素
     */
    public void add(Object element) {
        add(size(), element);
    }

    /**
     * 在指定位置插入元素
     *
     * @param index   插入位置
     * @param element 要插入的元素
     */
    public void add(int index, Object element) {
        ensureCapacity(size * 2 + 1); //容量扩充两倍,避免频繁扩容
        for (int i = size; i > index; i--) {
            nodes[i] = nodes[i - 1];
        }
        nodes[index] = element;
        size++;
    }

    /**
     * 删除元素
     *
     * @param index 要删除元素的位置
     * @return 被替换的旧元素
     */
    public Object remove(int index) {
        Object removeElement = nodes[index];
        for (int i = index; i < size - 1; i++) {
            nodes[i] = nodes[i + 1];
        }
        //nodes[size-1]=null; 数组大小已经减小1,该节点不会被访问到,没有必要清空
        size--;
        return removeElement;
    }

    /**
     * 设置元素
     *
     * @param index   要设置的元素位置
     * @param element 要设置的元素
     * @return 被替换的旧元素
     */
    public Object set(int index, Object element) {
        if (index < 0 || index >= size) {
            throw new ArrayIndexOutOfBoundsException();
        }
        Object oldElement = nodes[index];
        nodes[index] = element;
        return oldElement;
    }

    /**
     * 获取元素
     *
     * @param index 要获取的元素位置
     * @return 获取到的元素
     */
    public Object get(int index) {
        if (index < 0 || index >= size) {
            throw new ArrayIndexOutOfBoundsException();
        }
        return nodes[index];
    }

    /**
     * 查找某个元素的位置
     *
     * @param element 要查找的元素
     * @return 元素位置(不存在则返回-1)
     */
    public int indexOf(Object element) {
        for (int i=0;i<size;i++){
            if (element.equals(nodes[i])){
                return i;
            }
        }
        return -1;
    }


    /**
     * 清空数组
     */
    public void clear() {
        nodes = null;
        size = 0;
    }
}

测试类

package chapter2.arrayList;

public class TestArrayList {
    public static void main(String args[]){
        MyArrayList myArrayList=new MyArrayList();

        myArrayList.add("a");
        System.out.println("isEmpty:"+myArrayList.isEmpty());

        myArrayList.add("b");
        myArrayList.add("c");
        System.out.println("size:"+myArrayList.size());
        printList(myArrayList);

        myArrayList.add(1,"d");
        printList(myArrayList);

        System.out.println("remove: "+myArrayList.remove(2));
        //printList(myArrayList);
        System.out.println("contains b:"+myArrayList.contains("b"));

        System.out.println("replace:"+ myArrayList.set(0,"e"));
        printList(myArrayList);
        System.out.println("index of d:"+myArrayList.indexOf("d"));

        myArrayList.clear();
        System.out.println("isEmpty:"+myArrayList.isEmpty());

    }
    private static void printList(MyArrayList arrayList){
        for (int i=0;i<arrayList.size();i++){
            System.out.print(arrayList.get(i)+" ");
        }
        System.out.println();
    }
}

输出

isEmpty:false
size:3
a b c 
a d b c 
remove: b
contains b:false
replace:a
e d c 
index of d:1
isEmpty:true

3. LinkedList的简单实现

LinkedList 实现

package chapter2.linkedList;

public class MyLinkedList {
    private static class Node {
        Node prev;
        Node next;
        Object element; //节点存储的数据

        public Node(Object object, Node p, Node n) {
            element = object;
            prev = p;
            next = n;
        }
    }

    private Node beginMarker;   //开始标记节点
    private Node endMarker;     //结束标记节
    private int size;

    public MyLinkedList() {
        clear();
    }

    /**
     * 得到链表大小
     *
     * @return size
     */
    public int size() {
        return size;
    }

    /**
     * 判断链表是否为空
     *
     * @return true or false
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 判断链表是否包含某个元素
     *
     * @param element 要判断的元素
     * @return true or false
     */
    public boolean contains(Object element) {
        Node p = beginMarker;
        for (int i = 0; i < size; i++) {
            p = p.next;
            if (p.element.equals(element)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 在链表末尾插入元素
     *
     * @param element 要插入的元素
     */
    public void add(Object element) {
        add(size, element);
    }

    /**
     * 在指定位置插入元素
     *
     * @param index   插入位置
     * @param element 要插入的元素
     */
    public void add(int index, Object element) {
        addBefore(getNode(index),element);
    }

    /**
     * 在某一节点前插入元素
     *
     * @param node    该节点
     * @param element 要插入的元素
     */
    private void addBefore(Node node, Object element) {
        Node newNode = new Node(element, node.prev, node);
        node.prev.next = newNode;
        node.prev = newNode;
        size++;
    }

    /**
     * 删除节点
     *
     * @param index 要删除节点的位置
     * @return 被替换的旧节点的element
     */
    public Object remove(int index) {
        Node oldNode=getNode(index);
        remove(oldNode);
        return oldNode.element;
    }

    /**
     * 删除节点
     *
     * @param node 要删除的节点
     * @return 被删除的节点的element
     */
    private Object remove(Node node){
        node.prev.next=node.next;
        node.next.prev=node.prev;
        size--;
        return node.element;
    }

    /**
     * 设置元素
     *
     * @param index   要设置的元素位置
     * @param element 要设置的元素
     * @return 被替换的旧元素
     */
    public Object set(int index, Object element) {
        Node node = getNode(index);
        Object oldElement = node.element;
        node.element = element;
        return oldElement;
    }

    /**
     * 获取元素
     *
     * @param index 要获取的元素位置
     * @return 获取到的元素
     */
    public Object get(int index) {
        return getNode(index).element;
    }

    /**
     * 查找某个元素的位置
     *
     * @param element 要查找的元素
     * @return 元素位置(不存在则返回-1)
     */
    public int indexOf(Object element) {
        Node p = beginMarker;
        for (int i = 0; i < size; i++) {
            p = p.next;
            if (p.element.equals(element)) {
                return i;
            }
        }
        return -1;
    }


    /**
     * 清空数组
     */
    public void clear() {
        size = 0;
        beginMarker = new Node(null, null, null);
        endMarker = new Node(null, beginMarker, null);
        beginMarker.next = endMarker;
    }

    private Node getNode(int index) {
        Node p;
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException();
        }
        if (index < size / 2) {      //从链表头开始检索
            p = beginMarker.next;
            for (int i = 0; i < index; i++) {
                p = p.next;
            }
        } else {                 //从链表尾开始检索
            p = endMarker;
            for (int i = size; i > index; i--) {
                p = p.prev;
            }
        }
        return p;
    }
}

测试类(测试用例与上面 ArrayList 完全相同)

package chapter2.linkedList;

class TestLinkedList {
    public static void main(String args[]) {

        MyLinkedList myLinkedList = new MyLinkedList();

        myLinkedList.add("a");
        System.out.println("isEmpty:" + myLinkedList.isEmpty());

        myLinkedList.add("b");
        myLinkedList.add("c");
        System.out.println("size:" + myLinkedList.size());
        printList(myLinkedList);

        myLinkedList.add(1, "d");
        printList(myLinkedList);

        System.out.println("remove: " + myLinkedList.remove(2));
        //printList(myArrayList);
        System.out.println("contains b:" + myLinkedList.contains("b"));

        System.out.println("replace:" + myLinkedList.set(0, "e"));
        printList(myLinkedList);
        System.out.println("index of d:" + myLinkedList.indexOf("d"));

        myLinkedList.clear();
        System.out.println("isEmpty:" + myLinkedList.isEmpty());
    }

    /*打印链表*/
    private static void printList(MyLinkedList linkedList){
        for (int i=0;i<linkedList.size();i++){
            System.out.print(linkedList.get(i)+" ");
        }
        System.out.println();
    }
}

输出(与上面 ArrayList 的输出完全相同)

isEmpty:false
size:3
a b c 
a d b c 
remove: b
contains b:false
replace:a
e d c 
index of d:1
isEmpty:true

猜你喜欢

转载自blog.csdn.net/gtx1502/article/details/81433142