算法-反转单向链表

需求

在这里插入图片描述
在这里插入图片描述

思路

  • 链表必有节点,节点两要素:当前元素值,下一个节点地址
import java.util.Scanner;

// 定义一个单向链表
public class MyLinkedList<E> {
    int size = 0;

    // 顶一个私有的内部类,表示链表的节点
    public class Node {
        E data;
        Node next;
        public Node(E data, Node next) {
            this.data = data;
            this.next = next;
        }
    }
}

添加节点

  • 第一次插入直接插入头结点
  • 后面都使用尾插法,插入到最后一个元素的后面(所以需要一个一个遍历)
// 添加节点
public Node add(E e) {
    Node head = null;
    Scanner scanner = new Scanner(System.in);
    while (true) {
        System.out.println("请输入数据,输入exit退出");
        String data = scanner.next();

        if (data.equals("exit")) {
            break;
        }

        if (head == null) {
            // 如果头节点为空,直接创建一个新的节点
            head = new Node((E) data, null);
        } else {
            // 尾插法 添加新的节点
            // 如果头节点不为空,找到最后一个节点,然后在最后一个节点的后面添加一个新的节点
            Node temp = head;
            while (temp.next != null) {
                temp = temp.next;
            }
            // 在最后一个节点的后面添加一个新的节点
            temp.next = new Node((E) data, null);
        }
        size++;
    }
    return head;
}

遍历

// 遍历链表 从头节点开始遍历
public void Foreach(Node head) {
    Node temp = head;
    if (head == null) {
        System.out.println("链表为空");
        return;
    }
    while (temp != null) {
        System.out.println(temp.data + " ");
        temp = temp.next;
    }
}

链表指定位置反转

  • 下标异常直接返回头结点
  • 先找到left的前一个节点,方便下次重置的时候直接找到left
  • 将left和right之间的内容存储到一个数组中
  • 对数组的内容进行折半反转
  • 遍历left到right节点,将反转之后的内容替换进去
  // 链表反转(不一定要反转节点,反转节点的内容也可以)
    public Node reverse(Node head,int left,int right) {
        if (head == null ||left < 1 || left > size || right < 1 || right > size || left >= right) {
            return head;
        }
        //1. 找到left的前一个节点
        Node pre = null;
        Node leftNode = head;
        E[] data = (E[]) new Object[right - left + 1];
        for (int i = 1; i <= right; i++) {
            // 找到left的前一个节点
            if (i == left - 1) {
                pre = leftNode;
            }

            // 从left到right的节点的数据存储到数组中
            if (i >= left && i <= right){
                data[i - left] = leftNode.data;
            }
            // leftNode指向下一个节点
            leftNode = leftNode.next;


        }
        //2. 找到right的后一个节点
        Node rightNode = leftNode;

        // 3.反转data数组
        for (int i = 0; i < data.length / 2; i++) {
            E temp = data[i];
            data[i] = data[data.length - i - 1];
            data[data.length - i - 1] = temp;
        }

        // 4.从pre节点开始,将data数组中的数据赋值给链表中的节点
        for (int i = 0; i < data.length; i++) {
            pre.next.data = data[i];
            pre = pre.next;
        }
        return head;

    }

测试:

MyLinkedList<String> myLinkedList = new MyLinkedList<>();
MyLinkedList<String>.Node head = myLinkedList.add("aa");
myLinkedList.Foreach(head);
myLinkedList.reverse(head,2,4);
System.out.println("反转后的链表");
myLinkedList.Foreach(head);
  • 反转前的链表:aa bb cc dd ee ff gg
  • 反转后的链表:aa dd cc bb ee ff gg
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值