数据结构——单链表

106 阅读4分钟

数据结构——单链表的实现

链表的定义

  • 链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的

链表的实现

  1. 头插法 public void addFirst(int data){ }
  2. 尾插法 public void addLast(int data){ }
  3. 任意位置插入,第一个数据节点为0号下标 public void addIndex(int index,int data){ }
  4. 查找是否包含关键字key是否在单链表当中 public boolean contains(int key){ return false; }
  5. 删除第一次出现关键字为key的节点 public void remove(int key){ }
  6. 删除所有值为key的节点 public void removeAllKey(int key){ }
  7. 得到单链表的长度 public int size(){ return -1; }
  8. 清除所有的链表 public void clear() { }
  9. 打印链表 public void display() {}`

实现代码

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找到

        //链表和各个节点的位置

    }



        /*

        定义cur,保证头结点能够保持不变

        只要cur不为空就代表后面还有结点

         cur= cur.next通过这个条件达到遍历链表的目的地

            * */

    public void disply() {

        LineNode cur = this.head;

        while (cur != null) {

            System.out.print(cur.val + " ");

            cur= cur.next;

        }

    }



    @Override

    //求链表的结点数

    public int size() {

        int count = 0;

        LineNode cur = this.head;

        while (cur != null) {

            count++;

            cur= cur.next;

            //count++;

            //没遍历一个结点。计数器加一次,前后都可以

        }

        return count;

    }





    /*

    * 头插法

    *

    * 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;

        }

    }

    /*

    * 尾插法

    * 实例化一个节点

    * 找到链表最后一个节点,然后插入到最后

    *判断的条件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;

        }

    }

    /*

    * 在任意位置插入节点

    * 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;

    }

    /*

    * 删除结点

    *

    * */

    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;

    }



    /*

    *  删除所有值为key的节点

    *

    * */

    public void removeAllkey(int key) {

        if (this.head == null) {

            return;

        }

        LineNode prev = head;

        LineNode cur = head.next;

        while(cur != null) {

            if (cur.val == key ) {

                prev.next = cur.next;

                cur = cur.next;//继续遍历,找到下一个值为key的节点



            }else {

                prev = cur;//prev的移动是为了方便删除key节点

                cur = cur.next;

            }

        }

        if(head.val == key) {

            head = head.next;

        }



    }



    /*

    * 清空所有节点

    * */

    @Override

    public void clear() {

        LineNode cur = head;

        while (cur != null) {

            LineNode curNext = cur.next;//记录下cur的下一个节点,当cur清空时能够保证找到下一个节点

            //cur.val =null 将引用类型的值清空

            cur.next =null;

            cur = curNext;//跳转到下一个节点

        }

        head = null;//释放头节点



    }