单链表反转

本文介绍了如何在Java中实现单链表,包括增删查改等基本操作,并提供了两种反转单链表的方法:借助栈实现和使用多指针。栈反转通过遍历链表将元素压栈,然后依次出栈添加到新链表;多指针法则通过三个指针调整链表节点的连接关系。这两种方法直观易懂,适用于理解链表反转的原理。
摘要由CSDN通过智能技术生成

如何反转单链表?

定义链表

链表基础类,node


/**
 * 链表节点
 *
 * @author zab
 * @date 2022/5/19 22:54
 */
public class Node {
    public Object data;
    public Node next;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }
}

实现增删查的链表类

package zab.datastructures.list.single;

/**
 * 单链表
 *
 * @author zab
 * @date 2022/5/19 22:52
 */
public class SingleLinkedList<E> {

    private int size = 0;
    private Node firstNode = null;


    public Node getFirstNode() {
        return firstNode;
    }

    public void setFirstNode(Node firstNode) {
        this.firstNode = firstNode;
    }

    /**
     * 往单链表添加数据
     *
     * @author zab
     * @date 2022/5/29 22:39
     * @param e 链表元素
     * @return true 成功
     */
    public boolean add(E e) {
        //第一个节点的情况
        if (firstNode == null) {
            firstNode = new Node();
            firstNode.setData(e);
            size++;
            return true;
        }
        //非第一个节点
        //构建节点
        Node newNode = this.buildNode(e);
        if (size == 1) {
            firstNode.setNext(newNode);
            size++;
            return true;
        }

        Node node = firstNode.getNext();
        //遍历到最后一个节点,给最后一个节点设置next
        while (true) {
            if (node.getNext() == null) {
                node.setNext(newNode);
                break;
            }
            node = node.getNext();
        }

        size++;
        return true;
    }

    private Node buildNode(E e) {
        Node node = new Node();
        node.setData(e);
        node.setNext(null);
        return node;
    }

    /**
     * 按照index获取元素
     *
     * @author zab
     * @date 2022/5/29 22:39
     * @param index 下标
     * @return Node 元素结点
     */
    public Node get(int index) {
        if (index < 0) {
            return null;
        }
        if (index == 0 && firstNode != null) {
            return firstNode;
        }
        Node temp = firstNode;
        int flag = 0;
        //从头开始遍历,记录遍历下标
        while (temp != null) {
            if (flag == index) {
                return temp;
            }
            flag++;
            temp = temp.getNext();
        }

        return null;
    }

    /**
     * 删除指定元素
     *
     * @author zab
     * @date 2022/5/29 22:50
     * @param e 要删除的节点
     * @return true删除成功
     */
    public boolean remove(E e) {
        Node node = firstNode;
        //前驱节点
        Node preNode = null;
        //遍历找值一样的,并且记录前驱节点
        while (node != null && node.getData() != e) {
            preNode = node;
            node = node.getNext();
        }
        //循环完毕,有可能没找到,找到了node就有值,没找到,node就是最后一个节点的next(null)
        //node !=null  就是找到节点了,需要执行删除操作
        if (node != null) {
            //preNode是空,表示找到的节点是头结点
            if (preNode == null) {
                firstNode = node.getNext();
            } else {
                //非头结点
                preNode.setNext(node.getNext());
            }
            size--;
            return true;
        }

        return false;
    }

    public int getSize(){
        return size;
    }

}

借助栈实现反转

都说反转链表很难?不考虑时间空间复杂度,我们尝试一种最简单的方式,看图:

 我们有一个链表,然后遍历链表,把链表第0个放到栈底,把最后一个元素放到栈顶,最后根据栈的先进后出,把原先链表中的最后一个元素取出,添加新链表,作为第一个元素,以此类推,实现链表反转。

代码如下:

   /**
     * 用外力,栈
     */
    public static SingleLinkedList inverseList1(SingleLinkedList list) {
        Stack<Node> stack = new Stack<>();

        Node node = list.get(0);
        if (node == null || list.getSize() == 1) {
            return list;
        }

        while (node != null) {
            stack.push(node);
            node = node.getNext();

        }

        SingleLinkedList result = new SingleLinkedList();
        while (!stack.isEmpty()) {
            Node pop = stack.pop();
            result.add(pop.getData());
        }

        return result;
    }

利用多指针

多指针思路如下图

      如图所示,有三个指针begin、middle、end。最开始begin指向null,middle指向链表第一个元素,end指向第二个元素。遍历链表,直到end指向链表的最后一个元素的next(肯定为null)为止,遍历链表时,只需要做一件事,就是把middle的next指向begin,实现链表的反转。

代码如下:

    /**
     * 三指针法,用三个指针记录
     */
    public static SingleLinkedList inverseList2(SingleLinkedList list) {
        Node head = list.getFirstNode();
        if (head == null || head.getNext() == null) {
            return list;
        }
        Node begin = null;
        Node middle = head;
        Node end = head.getNext();
        while (true) {

            middle.setNext(begin);

            begin = middle;
            middle = end;
            end = end.getNext();

            if (end == null) {
                break;
            }
        }

        middle.setNext(begin);
        head = middle;
        list.setFirstNode(head);
        return list;
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值