算法通关村第一关——链表青铜挑战笔记

1.单链表的概念

1.1 链表的概念

元素间相互连接,包含多个节点,每个结点有个指向后续元素的next指针,最后一个元素指向null

1.2链表的相关概念

1.2.1节点与头节点

在链表中,每个点都由值指向下一个结点的地址组成的一个独立单元,称为一个节点(结点)

对于单链表,知道第一个元素就可以遍历访问整个列表,第一个节点称为头节点

1.2.2 虚拟节点

在做题以及在工程里经常会看到虚拟结点的概念,其实就是一个结点dummyNode,其next指针指向head,也就是dummyNode.next=head

因此,如果我们在算法里使用了虚拟结点,则要注意如果要获得head结点,或者从方法(函数)里返回的时候,则应使用dummyNode.next。

另外注意,dummyNode的val不会被使用,初始化为0或者-1等都是可以的。既然值不会使用,那虚拟结点有啥用呢?简单来说,就是为了方便我们处理首部结点,否则我们需要在代码里单独处理首部结点的问题。在链表反转里,我们会看到该方式可以大大降低解题难度。

2.创建链表

ListNode的next指向同为ListNode类型的对象,构造出了一个链条访问结构

所以链表就是从head开始,逐个开始向后访问,而每次所访问对象的类型都是一样的。

2.1 Java里规范的链表定义

 /**
  * Java里规范的链表定义
  */
 public class ListNode {
    private int data;
    private ListNode next;
    public ListNode(int data) {
         this.data = data;
     }
 ​
    public int getData() {
         return data;
     }
 ​
     public void setData(int data) {
         this.data = data;
    }
 ​
     public ListNode getNext() {
         return next;
    }
 ​
     public void setNext(ListNode next) {
         this.next = next;
    }
 }

2.2 在leetcode中算法题经常这样定义

违背了面向对象设计要求,但是更加简洁,因此算法题中广泛应用

/**
  * 在leetcode中算法题经常这样定义
  */
 public class ListNode {
     public int val;
     public ListNode next;
 ​
     ListNode(int x) {
         val = x;
         //这个一般作用不大,写了会更加规范
         next = null;
     }
 }
 ListNode listnode=new ListNode(1);

3.链表的增删改查
3.1 遍历链表

public static int getListLength(Node head) {
     int length = 0;
     Node node = head;
     while (node != null) {
         length++;
         node = node.next;
     }
     return length;
 }

3.2链表的插入

 /**
      * 链表插入
      * @param head       链表头节点
      * @param nodeInsert 待插入节点
      * @param position   待插入位置,从1开始
      * @return 插入后得到的链表头节点
      */
 public static Node insertNode(Node head, Node nodeInsert, int position) {
     if (head == null) {
         //这里可以认为待插入的结点就是链表的头结点,也可以抛出不能插入的异常
         return nodeInsert;
     }
     //已经存放的元素个数
     int size = getLength(head);
     if (position > size+1  || position < 1) {
         System.out.println("位置参数越界");
         return head;
     }
 ​
     //表头插入
     if (position == 1) {
         nodeInsert.next = head;
         // 这里可以直接 return nodeInsert;还可以这么写:
         head = nodeInsert;
         return head;
     }
 ​
     Node pNode = head;
     int count = 1;
     //这里position被上面的size被限制住了,不用考虑pNode=null
     while (count < position - 1) {
         pNode = pNode.next;
         count++;
     } 
     nodeInsert.next = pNode.next;
     pNode.next = nodeInsert;
 ​
     return head;
 }

3.3链表删除

 /**
      * 删除节点
      * @param head     链表头节点
      * @param position 删除节点位置,取值从1开始
      * @return 删除后的链表头节点
      */
 public static Node deleteNode(Node head, int position) {
     if (head == null) {
         return null;
     }
     int size = getListLength(head);
     //思考一下,这里为什么是size,而不是size+1
     if (position > size || position <1) {
         System.out.println("输入的参数有误");
         return head;
     }
     if (position == 1) {
         //curNode就是链表的新head
         return head.next;
     } else {
         Node cur = head;
         int count = 1;
         while (count < position - 1) {
             cur = cur.next;
             count++;
         }
         Node curNode = cur.next;
         cur.next = curNode.next;
         //上面两行可以直接简化成:cur.next=cur.next.next
     }
     return head;
 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值