数据结构学习笔记之链表

  1. 定义
      链表是一种物理单元上非连续、非顺序的存储结构,链表实际上由一系列节点组成,每个节点包括两个部分:用来存储数据的数据域和指向下一个节点的指针。
链表结构

  使用链表可以克服数组长度不可变的缺点,链表可以充分利用计算机的内存空间,实现灵活的内存动态管理,但是链表失去了数组随机读取元素的优点,每次读取元素都必须从头结点往后遍历,同时由于增加了指针,空间开销会大于数组。

  1. 使用
      根据链表的结构,可以设计出对应的链表类,链表类中包含两个属性,链表的头结点和链表中的元素个数。
public class LinkedList {

    private class Node{
        //数据域
        public E e;
        //指针域
        public Node next;
        public Node(E e, Node next){
            this.e = e;
            this.next = next;
        }
        ......
    }
    private Node head;
    private int size;
}

  (1)添加元素,当向链表添加元素时,需要考虑要添加的位置是否是头结点,具体流程如下:

添加元素

  具体的实现如下:

    //向索引为 index 的位置添加元素 E
    public void add(int index, E e){
        if(index < 0 || index > size) throw new IllegalArgumentException("参数无效!!");
        size ++;
        // 当为头结点时
        if(index == 0){
            head = new Node(e, head);
            return ;
        }
        Node pre = head;
        while(-- index  > 0) pre = pre.next;
        pre.next = new Node(e, pre.next);
    }

  (2)删除元素时,同样要考虑要删除的元素是否是头结点,具体流程如下:

删除节点

  具体实现如下:

    //移除索引 index 位置的元素
    public E remove(int index){
        if(index < 0 || index >= size) throw new IllegalArgumentException("参数无效!!");
        size --;
        E e;
        // 当为头结点时
        if(index == 0){
            e = head.e;
            head = head.next;
        // 移除非头结点的元素
        }else{
            Node pre = head;
            while( -- index  > 0) pre = pre.next;
            e = pre.e;
            pre.next = pre.next.next;
        }
        return e;
    }

  无论是删除还是添加操作,都必须判断当前要操作的节点是否是头结点,因为头结点是没有前节点的,所以操作和其他的节点不同,我们可以实现一个虚拟头节点,在链表的初始化时,就让头指针指向虚拟节点,让虚拟节点指向链表的真实头节点,这样的话链表头结点的添加和删除操作就和其他节点相同了,因为链表的头结点的前节点就是虚拟节点,链表的结构如下:

头结点

具体实现如下:


public class VirtualHeadLinkedList {
    private Node head;
    private int size;
    public VirtualHeadLinkedList(){
        head = new Node();
    }

 //向索引为 index 的位置添加元素 E
    public void add(int index, E e){
        if(index < 0 || index > size) throw new IllegalArgumentException("参数无效!!");
        size ++;
        Node pre = head;
        while( index --  > 0) pre = pre.next;
        pre.next = new Node(e, pre.next);
    }

    //移除索引 index 位置的元素
    public E remove(int index){
        if(index < 0 || index >= size) throw new IllegalArgumentException("参数无效!!");
        size --;
        Node pre = head;
        while( index --  > 0) pre = pre.next;
        E e = pre.e;
        pre.next = pre.next.next;
        return e;
    }
}
  1. 扩展
      使用链表实现栈、队列(提示:可以增加一个tail指针)
代码地址

你可能感兴趣的:(数据结构学习笔记之链表)