算法通关村第一关——链表青铜挑战笔记-【链表基础】

本文介绍了Java中链表的基本概念,包括单链表的结构和头节点的重要性。详细讨论了如何在链表的头部、中间和尾部添加和删除元素,并提供了相应的代码示例。同时提到了使用虚拟节点简化头节点操作的方法,以及双向链表的构造和操作方式。
摘要由CSDN通过智能技术生成

目标:

1.理解Java如何构造出链表的
2.链表增加元素,首部、中间和尾部分别会有什么问题,该如何处理?
3.链表删除元素,首部、中间和尾部分别会有什么问题,该如何处理?
4.双向链表是如何构造的,如何实现元素的插入和删除。

链表概念

单链表

链表是由指针串联起来的线性结构,每个节点由数据和指向下一个节点的指针构成,最后一个节点的指针域指向null。

image.png
注意:单链表后继只能指向一个节点,但是一个节点可以被多个节点指向。
例如:下图2中 c1指向多个节点所以,不满足单链表


其他概念

**头节点:**链表的第一个节点,知道头结点才可遍历整个链表,很重要
**虚拟节点:**dummyNode,其next指针指向head。用来便利对头结点的操作,统一操作逻辑。

构造链表

链表定义

public class ListNode {
    public int val;
    public ListNode next;

    ListNode(int x) {
        val = x;
        next = null;
    }
}
ListNode listnode=new ListNode(1);

链表初始化

 public static void main(String[] args) {
        int[] a = {1, 2, 3, 4, 5, 6};
        Node head = initLinkedList(a);
        System.out.println(head);
    }

    private static Node initLinkedList(int[] array) {
        Node head = null, cur = null;
        for (int i = 0; i < array.length; i++) {
            Node newNode = new Node(array[i]);
            newNode.next = null;
            if (i == 0) {
                head = newNode;
                cur = newNode;
            } else {
                cur.next = newNode;
                cur = newNode;
            }
        }
        return head;
    }
static class Node {
        public int val;
        public Node next;

        Node(int x) {
            val = x;
            next = null;
        }
    }

可看到如下结构:
1689815471728.png

遍历

public static String toString(Node head) {
        Node current = head;
        StringBuilder sb = new StringBuilder();
        while (current != null) {
            sb.append(current.data).append("\t");
            current = current.next;
        }
        return sb.toString();
    }


这里直接操作head,不进行赋值也可以。不会影响外面传入的原head的指向,但如果在遍历的同时还需要对链表有其他操作最好还是需要保留头结点的指向。

新增

考虑三种插入位置的情况。头部新增单独处理,中间插入和尾部插入逻辑相同

头部插入

需注意插入新的头结点后,要将head指针指向新的头结点

中间插入

要注意插入顺序 先将新节点指向后一个节点后,再将前一个节点指向新节点(顺序错误会导致后面的链表失连)
newNode.next = afterNode.next;
preNode.next = newNode;

尾部插入

实现时可使用中间插入逻辑
只要将尾结点指向新结点就行

/**
     * 链表插入
     *
     * @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;
            head = nodeInsert;
            return head;
        }
    	//中间和尾部插入
        Node pNode = head;
        int count = 1;
        //停在插入位置的前一个节点进行操作所以position-1
        while (count < position - 1) {
            pNode = pNode.next;
            count++;
        }
        //注意这里的 顺序 要先将待插入节点指向下一个节点,再将前一个节点指向待插入节点
        nodeInsert.next = pNode.next;
        pNode.next = nodeInsert;

        return head;
    }

删除

也是考虑,头部删除、中间删除、末尾删除3中情况。并在指定元素的前一个进行操作

头部删除

head往后移动一位就可以 head=head.next

中间删除

在删除节点的前一个节点进行操作,只需要cur.next=cur.next.next就可以了。末尾节点删除也是一样

尾部删除

与中间删除逻辑一样,在删除节点的前一个节点进行操作

public static Node deleteNode(Node head, int position) {
        if (head == null) {
            return null;
        }
        int size = getLength(head);
        if (position > size || position <= 0) {
            System.out.println("输入的参数有误");
            return head;
        }

        if (position==1){
            head=head.next;
            head.next=null;
            return head;
        }
        Node cur=head;
        int count=1;
        //也是停留在删除元素的前一个进行操作
        while (count<position-1){
            cur=cur.next;
            count++;
        }
        cur.next=cur.next.next;
        return head;
    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值