链表(单链表)

94 阅读4分钟

1.链表的简介

链表是一种物理存储结构上非连续存储结构

​编辑

​编辑

  1. data:表示链表的值(数据域)
  2. next: 表示存储的下一个结点的地址(指针域)
  3. 链表就是通过这样的链式存储方式进行连接,可以很大的节省开支,因为插入一个元素不用像顺序表那样移动多余的元素

2.建立链表

为了方便讲解,我这里按照自己的思路建立了一个链表

定义链表的节点
  public class Mystringlist  implements List<Void> {
    /*
    * 将结点LineNode定义为内部类
    * 内部类  由诺干个成员构成
    * Linenode   由数据域和next域构成,所以定义为内部类
    * next引用的是一个结点的类型,存储的是下一个结点的地址,
    * 相当于 LineNode next = new LineNode();
    *   public LineNode(int val) {
            this.val = val;
        }
        * 因为不知道后面的结点,只知道当前结点的是,next的值为null
    * */
    static class LineNode {
        public int val ;
        public LineNode next;
        public LineNode(int val) {

            this.val = val;
        }
    }
    public LineNode head;//头结点的标识,是属于链表的成员定义在内部类的外部
    /*
    * 建立链表*/
    public void creatList() {
        LineNode node1 =new LineNode(12);
        LineNode node2 =new LineNode(22);
        LineNode node3 =new LineNode(32);
        LineNode node4 =new LineNode(42);
        LineNode node5 =new LineNode(52);
        LineNode node6 =new LineNode(444);
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = node6;

        this.head = node1;//让head指向第一个位置,当变量回收过后,任然可以通过head找到
        //链表和各个节点的位置
    }  

3.头插法

顾名思义,在链表的头结点进行插入元素

​编辑

  1. 在head头结点的前面插入node结点
  2. 插入过后,node结点的下一位就是原来的head结点:node.next = this.head;
  3. 此时node就成为了新的结点:this.head = node;
 /*
    * 头插法
    *在头节点的前面进行插入
    * node.next = this.head;
    * 代表要插入的节点和原来链表的第一个节点相连接
    *   this.head = node;
    * 表示插入的节点就是头节点
    * */
    public void addFirst(int data) {
        LineNode node = new LineNode(data);
        if (this.head == null) {
            this.head = node;
        }else {
            node.next = this.head;
            this.head = node;
        }
    }

4.尾插法

就是在链表的末尾进行插入结点的操作

​编辑

  1. 首先找到链表的最后一个结点,判断的条件是cur.next == null
  2. 然后插入node结点:cur.next = node
/*
    * 尾插法
    * 实例化一个节点
    * 找到链表最后一个节点,然后插入到最后
    *判断的条件cur.next != null
    *
    * */
    public void addLast(int data){
        LineNode node = new LineNode(data);
        LineNode cur = this.head;
        if (this.head == null) {
            this.head = node;
        }else {
            while (cur.next != null) {
                cur = cur.next;
        }
            cur.next = node;
        }
    }

5.在任意位置插入结点

​编辑

  1. cur为此时要插入结点的位置
  2. 插入node结点,原来cur的下一个是3,插入过后cur的下一个结点就是4:cur.next = node;
  3. 所以node下一位就是3(原来cur的下一个位置):node.next = cur.next;
 /*
    * 在任意位置插入节点
    * int indx 插入节点的位置
    * */
    public void addIndex(int indx,int data) {
        if (indx < 0 || indx > size()) {
            //自定义一个异常
            return;
        }
        if (indx == 0) {
            //头插法,插入到链表的首部
            addFirst(data);
            return;
        }
        if (indx == size()) {
            //插入到链表的最后一个位置,尾插法
            addLast(data);
            return;
        }
        LineNode cur = search(indx);//找到要插入节点的位置
        LineNode node = new LineNode(data);//创建一个新的节点
        node.next = cur.next;
        cur.next = node;
    }
 /*
    * count代表头节点的位置
    * indx代表插入节点
    * 当头节点不断地后移,知道到达要插入节点的前一个节点的位置
    * 返回该节点的位置即可*/
    private LineNode search(int indx) {
        LineNode cur = this.head;
        int count = 0;
        while (count != indx - 1) {
            cur = cur.next;
            count++;
        }
        return cur;
    }

6.删除节点

​编辑

  1. 首先需要找到要删除节点的前驱,这样才能连接链表
  2. 删除del节点过后,cur的下一个结点就是3: cur.next = del.next; 
 /*
    * 删除结点
    *
    * */
    public void remove1(int key){
        //头节点删除
        if (this.head.val ==key) {
            this.head = this.head.next;
            return;
        }
        //找到要删除结点的前驱
        LineNode cur = find(key);
        if (cur == null) {
            System.out.println("error");
            return ;
        }
        //删除
        //del是要删除的结点
        LineNode del = cur.next;
        cur.next = del.next;

    }
    //找到删除结点的前驱
    private LineNode find(int key) {
        LineNode cur = this.head;
        while (cur.next != null) {
            if (cur.next.val == key) {
                return cur;
            }
            //不断循环下一个结点直到找到key
            cur = cur.next;
        }
        return null;
    }

ps:需要了解更多的数据结构知识点,可以留言,免费领取《大话数据结构》pdf