1、第一关 青铜挑战——小白也能学会的链表(Java)

目录

任务内容

一、Java如何构造链表

二、链表的增删改查

1.遍历链表

1.1获取链表长度

1.2遍历链表节点值

2.链表插入

2.1 头插法

2.2 中间插入

2.3 尾部插入

实现代码

3.链表删除

3.1 删除表头节点

3.2 删除中间节点

3.3 删除尾节点

实现代码

三、扩展题


任务内容

1、Java是如何构造链表

2、链表如何进行增删改查

一、Java如何构造链表

构建出节点对象

    public class ListNode{
        public int var;//节点值
        public ListNode next;//节点的后继节点

        public ListNode(int var){//节点带参构造方法
            this.var = var;
        }
    }

根据已有数组,遍历数组,构建链表

    public static void main(String[] args) {
        int[] a = {1,3,5,7,9,11};
        ListNode head = initListNode(a);
        System.out.println(outputList(head));
    }
    private static ListNode initListNode(int[] array){
        ListNode head = null,cur = null;//初始化头节点,当前节点
        for (int i = 0; i < array.length; i++) {
            //为数组中每个值创造一个节点
            ListNode node = new ListNode(array[i]);
            if (i == 0){//从第一个节点开始,头节点head不变,变动cur节点
                head = node;
                cur = node;
            }else{
                cur.next = node;
                cur = node;
            }
        }
        return head;
    }

二、链表的增删改查

1.遍历链表

就单链表来说,不论什么操作,都是要从链表的头节点开始向后一个个节点访问,再进行操作,故,链表的头节点非常重要,一定要记牢。

1.1获取链表长度

/**
     * 获取链表长度
     * @param head 头节点
     * @return     链表长度
     */
    public static int getListLength(ListNode head){
        int length = 0;//用于计数
        ListNode cur = head;//一般创造一个临时指针来代替头节点向后遍历(牢记:头节点需谨慎改变)
        while (cur != null){
            length ++;
            cur = cur.next;
        }
        return length;
    }

1.2遍历链表节点值

借用stringbuilder类来输出链表

    /**
     * 遍历输出链表
     * @param head 头节点
     * @return     链表输出形式
     */
    public static String outputList(ListNode head){
        StringBuilder sb = new StringBuilder();
        ListNode cur = head;
        while (cur != null){
            if (cur.next == null)
                sb.append(cur.var);
            else 
                sb.append(cur.var).append("->");
            cur = cur.next;
        }
        return sb.toString();
    }

2.链表插入

链表插入有三种方法

2.1 头插法

头节点很重要,在头部插入新节点后,需要改变head指向新链表表头。

2.2 中间插入

中间插入节点,必须从头节点开始遍历找到要插入的位置,记住确认插入位置的前驱节点(这非常重要)。保持先来先主动原则:首先新节点的后继先接入,然后再使新节点的前驱节点接入新节点,例如下图:记住cur = node(15),首先new.next = node(7),然后cur.next = new

2.3 尾部插入

只需将遍历链表,将尾节点指向新节点就行。

实现代码

    /**
     * 插入节点
     * @param head     头节点
     * @param newNode  待插入节点
     * @param position 待插入位置,从1开始
     * @return         插入后得到的链表头节点
     */
    public static ListNode insertNewNode(ListNode head,ListNode newNode,int position){
        if (head == null){//如果链表为空,则插入节点就是链表的头节点
            head = newNode;
            return newNode;
        }

        int size = getListLength(head);//得到已经存放的节点个数
        if (position > size+1 || position < 1){ //判断插入位置是否合法
            System.out.println("位置参数越界");
            return head;
        }

        //表头插入
        if (position == 1){
            newNode.next = head;
            head = newNode; //更新表节点
            return head;
        }

        // 表中和表尾插入
        int count = 1; //设一个计数,便于寻找所插入位置的前一个节点
        ListNode cur = head; //从头节点开始寻找
        while (count < position - 1){ //例如,position == 3 ,找到第二个节点即可,count == 2结束循环,故count < 2(position -1)作为条件
            count ++;
            cur = cur.next;
        }
        //插入节点具体操作
        newNode.next = cur.next;
        cur.next = newNode;

        System.out.println("在链表第" +position+"个位置,插入节点"+newNode.var+"成功");
        return head;
    }

3.链表删除

3.1 删除表头节点

只需将头节点head更新为head.next就行。jvm有gc回收机制,没用地址引用会直接清楚堆中对象。

3.2 删除中间节点

找到删除节点位置的前驱节点,用于cur引用标记,将cur.next = cur.next.next。

3.3 删除尾节点

同删除中间节点也可实现,或者cur.next = null

实现代码

    /**
     * 删除节点
     * @param head     头节点
     * @param position 删除节点位置,取值从1开始
     * @return         删除后的链表头节点
     */
    public static ListNode deleteListNode(ListNode head,int position){
        if (head == null){
            System.out.println("该链表为空,没有可删除的节点");
            return null;
        }
        
        int size = getListLength(head);
        if (position > size || position <1){
            //思考一下,这里为什么是size,而不是size+1
            //因为插入节点时,可插入第size+1位置,而删除节点不能删除size+1位置。
            System.out.println("输入位置参数有误");
            return head;
        }
        
        //删除表头节点
        if (position == 1){
            head = head.next;
            return head;
        }else {
            //删除表中和表尾节点
            ListNode cur = head;
            int count = 1;
            while (count < position -1){//找到删除节点的前趋节点
                count++;
                cur = cur.next;
            }
            //删除节点具体操作
            cur.next = cur.next.next;
        }
        return head;
    }

三、扩展题

如果链表是单调递增的,将元素插入到合适的位置,序列仍然保持单调,该如何实现?

思路:同为插入新节点,只需遍历整个链表的节点,每个节点与插入节点值进行大小比较,找到合适的插入位置,再进行链表插入。

例:将数组array{1,3,5,7,9,11}用链表实现。并①插入新节点4,②插入新节点12。

    public static void main(String[] args) {
        int[] array = {1,3,5,7,9,11};

        //初始化链表
        Node head = initListNode(array);
        //插入新节点4
        head = insertNewNode(head,new Node(4));
        //插入新节点12
        head = insertNewNode(head,new Node(12));
        System.out.println(toString(head));
    }

    /**
     * 插入新节点,并保持链表单调
     * @param head    头节点
     * @param newNode 待插入节点
     * @return 插入后的链表头节点
     */
    public static Node insertNewNode(Node head,Node newNode){
        if (head == null)
            return newNode;
        Node cur0 = head;//遍历,依次与插入节点比较
        Node cur1 = head;//记录插入位置的前一个节点
        int count = 0;//记录比较次数,当比较次数达到链表最大长度时,将新节点插入表尾

        while (cur0.var <= newNode.var){//遍历链表,节点一一比较,找到待插入位置。
            count ++;
            if (count >= getListLength(head)){//比较次数达到链表最大长度,说明已经达到链表表尾,将cur1指向表尾即可退出循环。
                cur1 = cur0;
                break;
            }
            cur1 = cur0;
            cur0 = cur0.next;
        }
        newNode.next = cur1.next;
        cur1.next = newNode;
        return head;
    }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值