上一节我们实现并优化了动态数组的创建和基础功能的实现,这节进行链表的学习。

1.以缺陷提出新的解决思路

1.动态数组有个明细的缺点,可能会造成内存空间的大量浪费而链表可以做到用多少就申请多少。

2.链表的概念

1.链表是一种链式存储的线性表,所有元素的内存地址不一定是连续的,如下所示,链表包含头节点尾结点 ,节点之间通过节点地址进行连接。




python 链表怎么定义 python怎么写链表_python3怎么创建一个链表

链表实例



3.链表的创建

根据链表的结构进行创建链表对象:1. 一个节点中含有节点元素(任意类型) 和下一个节点的地址。2.头节点,头节点不包含元素,只有下一个节点地址和整个链表的大小。所以根据需要就可以创建出对应链表对象。




python 链表怎么定义 python怎么写链表_python3怎么创建一个链表_02

链表创建图示



//    链表长度    private   int size ;//    首节点    private Node first;    private static class Node{//        链表元素          E element;//          下一个节点          Node next;        public Node(E element, Node next) {            this.element = element;            this.next = next;        }    }

4.链表接口方法

链表常用的接口方法与动态数组(ArrayList)大致相同,所以采用实现接口的方式:public interface PublicInterface {    int size(); //元素的数量    boolean isEmpty(); //是否为空    boolean contains(E element); // 是否包含某个元素    void add(E  element);  // 添加元素到最后面    E  get(int index); // 返回index位置对应的元素    E set(int index,E element); // 设置index位置添加元素    void add(int index,E element); // 往index位置添加元素    E remove(int index); // 删除index位置对应的元素    int indexOf(E element); //查看元素的位置    void clear(); // 清除所有的元素}

5.提取动态数组与链表相同代码

动态数组和链表中如查看动态数组/链表数量 、是否为空的实现方式相同,所以采用继承的方式提取相同的代码:public abstract class AbstructList implements PublicInterface {    //    链表长度    protected int size ;    @Override    public int size() {        return size;    }    @Override    public boolean isEmpty() {        return size == 0;    }    @Override    public boolean contains(E element) {        return   indexOf(element) != NOT_DATA_FIND;    }    @Override    public void add(E element) {        add(size,element);    }}其中: 1. AbstructList 实现接口,但却不重写所有方法,采用抽象类方式。           2. 将size 提取到抽象类中 ,设置为 protected。           3.动态数组和链表来继承这个抽象类。

6.通过索引获取节点对象

1.在进行链表节点添加、删除等功能实现时都需要获取到某个节点对应的节点或者节点元素,所以创建一个私有的方法来通过索引获取到对应的节点对象:  /**     * 通过索引获取节点     * @param index     * @return     */    private Node getNode(int index){        if(index < 0 || index >= size){            throw  new IndexOutOfBoundsException("Index:" + index + " " +   "Size" + size);        }        Node node = first;        for(int i =0 ; i < index ; i++){            node = node.next;        }        return node;    }

7.节点元素获取、通过索引设置节点元素

通过刚刚创建的通过索引获取节点对象的方法来进行实现:// 获取索引对应的节点元素值  @Override    public E get(int index) {        Node node = getNode(index);        return node.element;    }// 根据索引设置元素值  @Override    public E set(int index, E element) {        Node node = getNode(index);        E old = node.element;        node.element = element;        return old;    }

8.链表在指定索引添加节点

如图所示,如果我们要添加1号节点到0、2节点之间,需要进行的步骤:  1. 通过索引找到指定索引的上一个节点 定义为prev。  2.创建一个节点newNode,使节点的next为 prev.next.  3.prev的下一个节点为newNode 。    其中如果索引为零的特殊情况,通过first解决,即可实现指定索引添加节点。




python 链表怎么定义 python怎么写链表_python3怎么创建一个链表_03

链表节点添加



@Override    public void add(int index, E element) {        if(index == 0 ){           first = new Node<>(element,first);        }else{            //       找到index的上一个节点            Node prev = getNode(index - 1);      //        创建一个节点 设置下一个节点为index上一个节点的next,prev的next要指向它            prev.next = new Node<>(element,prev.next);        }        size ++ ;    }

9.链表节点删除

如图所示,要进行指定索引节点的删除(删除节点1):1.通过索引获取到上一个节点 prev。2.prev的下一个节点为prev.next.next。3.如果是删除索引为0的节点,即first = first.next。即可实现指定索引删除节点的功能。




python 链表怎么定义 python怎么写链表_python 链表怎么定义_04

链表节点删除



@Override    public E remove(int index) {        Node node = first;        if(index == 0){            first = first.next;        }else{            //        先找出index上一个节点            Node prev = getNode(index-1);            node = prev.next;            prev.next = prev.next.next;        }        size --;        return node.element;    }

10.链表的清空

链表的清空,只需要将断开LinkedList指向的节点即可实现链表的清空,然后0节点被销毁,依次进行,所有节点被销毁。




python 链表怎么定义 python怎么写链表_ide_05

链表的清空



// 链表的清空    @Override    public void clear() {      size = 0;      first = null;    }