• 单链表


           链表是一系列的存储数据元素的单元通过指针串起来形成的,因此每个单元至少有两个域,一个域用于数据元素的存储,另一个域是指向其他单元的指针。这里具有一个数据域和多个指针域的存储单元通常称为节点(node)。

           一种最简单的节点结构如图所示:

     它是构成单链表的基本节点结构,在节点中数据域用来存储数据元素,指针域用于指向下一个具有相同构成的节点。(因为其只有一个指针节点,称为单链表)。

     链表的第一个节点和最后一个节点,分别称为链表的首节点和尾结点,尾结点的特征为next 为 null。

     带头结点的链表,头结点不存放有效数据,next指向第一个有效结点。

    初始化头结点head如下:

     插入结点:

    1. 头插法:
      public void addHead(E ele){
            //创建一个新节点
            Node newNode = new Node(ele,null);
            //新节点的直接后继
            newNode.next = head.next;
      //新节点的前驱为head head.next
      = newNode; size++; //记录有效元素的个数 }

      初始只有一个头结点,head.next 为null,新创建的结点的next应该指向head的next域。插入第一个节点:

                 

                       插入第二个结点:

                      2.选定位置插入结点元素

    public void add(int index,E element){
    
          //找到前一个节点,从头结点开始
          Node p = head;
          //判断参数合法性
          if(index < 0 || index > size){
              throw new RuntimeException("参数不合法!");
          }else {
              for (int j = 0; j < index; j++) {
                  p = p.next;
              }
          }
              //创建一个新节点
              Node newNode = new Node(element, null);
              //新节点的直接后继
              newNode.next = p.next;
              //新节点的直接前驱
              p.next = newNode;
    
          size++;
      }

    size为有效元素的个数,加入要插入到index = 2 的位置,应该先找到其前驱结点,即1号位置,(当for循环两次之后,其P指针所在的位置如图)

     

     创建新节点,找到其直接前驱和直接后继,便插入成功。

                3.尾插法

          尾插法便是指定位置插入数据的特殊情况,具体实现见代码。

    package 线性表;
    
    public class MyLinkList<E> {
        private Node<E> head;
                //节点数
                private int size;
    
        public MyLinkList(){
                    //初始化head 结点
                    this.head = new Node<E>((E)new Object(),null);
                }
    
                class Node<E> {
                    E data;     //要存储的数据
                    Node next;  //引用
    
                    public Node(E data) {
                        this.data = data;
                    }
    
                    public Node(E data, Node next) {
                        this.data = data;
                        this.next = next;
            }
        }
    
        /**
         * 得到节点个数
         * @return
         */
      public int size(){
          return size;
      }
    
        /**
         *
         * @param index
         * @return
         */
      public E get (int index) {
          //需要从头节点开始查找
          //定义一个引用
          Node p = head;
          if (index < 0 || index >= size) {
              throw new RuntimeException("参数不合法!");
          } else {
              for (int i = 0; i <= index; i++) {
                  p = p.next;
              }
          }
          return (E) p.data;
      }
        /**
         * 判断是否为空
         * @return
         */
      public boolean empty(){
          return size == 0;
      }
    
        /**
         * 指定位置添加元素
         * @param index
         * @param element
         */
      public void add(int index,E element){
    
          //找到前一个节点,从头结点开始
          Node p = head;
          //判断参数合法性
          if(index < 0 || index > size){
              throw new RuntimeException("参数不合法!");
          }else {
              for (int j = 0; j < index; j++) {
                  p = p.next;
              }
          }
              //创建一个新节点
              Node newNode = new Node(element, null);
              //新节点的直接后继
              newNode.next = p.next;
              //新节点的直接前驱
              p.next = newNode;
    
          size++;
      }
    
        /**
         * 头插法添加元素
         * @param ele
         */
      public void addHead(E ele){
          //创建一个新节点
          Node newNode = new Node(ele,null);
          //新节点的直接后继
          newNode.next = head.next;
          head.next = newNode;
          size++;
    
      }
    
        /**
         * 尾插法
         * @param ele
         */
      public void addTail(E ele){
           this.add(size,ele);
      }
    
        /**
         * 删除指定位置元素
         * @param index
         */
      public void delete(int index){
          //从头节点开始遍历
          Node p = head;
          //找到该节点的前一个结点
          if(index < 0 || index > size){
              throw new RuntimeException("参数不合法!");
          }else {
              for (int i = 0; i < index; i++) {
                  p = p.next;
              }
              //改变指向
              p.next = p.next.next;
              //更新节点数
              size--;
          }
      }
      public void show(){
          Node p = head;
          for (int i = 0; i < size; i++) {
              p = p.next;
              System.out.print(p.data + " ");
          }
      }
    }
    package 线性表;
    
    public class MyLinkListTest {
        public static void main(String[] args) {
            MyLinkList<Integer> ml = new MyLinkList<>();
    
            ml.addHead(1);
            ml.add(1,3);
            ml.addHead(2);
            ml.addHead(5);
            ml.addTail(6);
            ml.delete(0);
    
            System.out.println(ml.empty());
            System.out.println(ml.get(0));
            System.out.println(ml.get(1));
            ml.show();
    
    
        }
    }

    结果如图:

  • 相关阅读:
    PAT甲级1056Mice and Rice
    李宏毅机器学习课程笔记-5.3神经网络中的反向传播算法
    李宏毅机器学习课程笔记-5.2神经网络为什么要是深度的
    PAT甲级1014Waiting in Line
    python批量处理邮件:poplib和email快速上手教程
    李宏毅机器学习课程笔记-5.1深度学习之引言
    李宏毅机器学习课程笔记-4.2分类模型之概率生成模型
    李宏毅机器学习课程笔记-4.1分类简介及其与回归的区别
    类自动加载封装类
    var与let循环中经典问题
  • 原文地址:https://www.cnblogs.com/128-cdy/p/11925267.html
Copyright © 2020-2023  润新知