首页 > 其他分享 >单向链表使用

单向链表使用

时间:2024-04-07 09:31:45浏览次数:20  
标签:current head ListNode 单向 next 链表 使用 null 节点

单向链表

包含解决的问题:

  • 求单链表中有效节点的个数
  • 查找单链表中的倒数第k个结点 - 使用双指针实现 【新浪面试题】
  • 单链表的反转 - 通过栈的方式实现
  • 从尾到头打印单链表 - 方式1:递归实现 。 方式2:Stack栈实现
  • 合并两个有序的单链表,合并之后的链表依然有序。

代码示例:

// 定义链表节点
class ListNode {
    int val;
    ListNode next;

    ListNode(int val) {
        this.val = val;
        this.next = null;
    }
}

// 定义单向链表
public class LinkedList {
    private ListNode head; // 头节点

    // 求单链表中有效节点的个数
    public int getLength() {
        int length = 0;
        ListNode current = head;
        while (current != null) {
            length++;
            current = current.next;
        }
        return length;
    }

    // 查找单链表中的倒数第k个结点
    public ListNode findKthFromEnd(int k) {
        if (k <= 0 || head == null)
            return null;

        ListNode fast = head;
        ListNode slow = head;

        // 快指针先移动k步
        for (int i = 0; i < k; i++) {
            if (fast == null)
                return null;
            fast = fast.next;
        }

        // 快慢指针一起移动,直到快指针到达末尾
        while (fast != null) {
            fast = fast.next;
            slow = slow.next;
        }

        return slow;
    }

    // 单链表的反转
    public void reverse() {
        if (head == null || head.next == null)
            return;

        ListNode prev = null;
        ListNode current = head;
        ListNode next = null;

        while (current != null) {
            next = current.next; // 保存下一个节点
            current.next = prev; // 当前节点指向前一个节点
            prev = current; // 更新前一个节点
            current = next; // 更新当前节点
        }

        head = prev; // 更新头节点
    }
    
 	// 反转链表(通过栈实现)
    public void reverseByStack() {
        if (head == null || head.next == null)
            return;

        Stack<ListNode> stack = new Stack<>();
        ListNode current = head;

        // 将链表节点压入栈中
        while (current != null) {
            stack.push(current);
            current = current.next;
        }

        // 从栈中弹出节点,重新构建链表
        head = stack.pop();
        current = head;
        while (!stack.isEmpty()) {
            current.next = stack.pop();
            current = current.next;
        }
        current.next = null; // 最后一个节点的next置为null,防止形成环
    }

    // 从尾到头打印单链表(反向遍历)
    public void reversePrint() {
        if (head == null)
            return;

        // 使用递归实现反向打印
        reversePrint(head);
    }

    private void reversePrint(ListNode node) {
        if (node == null)
            return;

        reversePrint(node.next);
        System.out.print(node.val + " ");
    }

    // 从尾到头打印单链表(Stack栈)
    public void reversePrintByStack() {
        if (head == null)
            return;

        Stack<ListNode> stack = new Stack<>();
        ListNode current = head;

        // 将链表节点压入栈中
        while (current != null) {
            stack.push(current);
            current = current.next;
        }

        // 弹出栈中的元素并打印
        while (!stack.isEmpty()) {
            System.out.print(stack.pop().val + " ");
        }
    }

    // 合并两个有序的单链表,合并之后的链表依然有序
    public static ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(-1); // 创建一个虚拟头节点
        ListNode current = dummy;

        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                current.next = l1;
                l1 = l1.next;
            } else {
                current.next = l2;
                l2 = l2.next;
            }
            current = current.next;
        }

        // 将剩余节点连接到结果链表中
        if (l1 != null) {
            current.next = l1;
        } else {
            current.next = l2;
        }
        return dummy.next;
    }
}

标签:current,head,ListNode,单向,next,链表,使用,null,节点
From: https://blog.csdn.net/m0_72560900/article/details/137449366

相关文章

  • 使用Python的turtle模块绘制美丽的樱花树
    引言Python的turtle模块是一个直观的图形化编程工具,让用户通过控制海龟在屏幕上的移动来绘制各种形状和图案。turtle模块的独特之处在于其简洁易懂的操作方式以及与用户的互动性。用户可以轻松地通过使用诸如前进、后退、左转、右转等基本命令,来编写程序控制海龟的行动路径,从而创......
  • C++多线程:async、future、packaged_task、promise、shared_future的学习与使用(九)
    1、异步任务线程异步线程的概念:异步:就是非同步,同步就是必须一个一个的执行,异步可以两个事情一起干异步线程:异步线程就相当于把非关联的两件事分开找两个线程去执行,而分开的那个就是异步线程举例:例如登录信息,用户登录完毕主线程肯定是需要去及时响应用户的请求的,而系统设......
  • dd if=devzero of=的含义是什么?Linux 下的dd命令使用详解
    ddif=/dev/zeroof=的含义是什么?Linux下的dd命令使用详解一、dd命令的解释dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换。注意:指定数字的地方若以下列字符结尾,则乘以相应的数字:b=512;c=1;k=1024;w=2参数注释:1.if=文件名:输入文件名,缺省为标准输入。即指定源文......
  • 使用POI填充Word文档,一些注意事项以及解决办法
    有这样一个需求:需要将用户输入的数据填写到准备好的Word模版中并提供下载,最终选择POI-tl和POI来完成上述需求。在这个过程中,主要遇到了以下两个问题:1.Word的两个格式doc和docx(两种文件的区别大家可以自行百度了解下),POI并没有提供统一的处理类。分别用HWPFDocument处理doc......
  • Typora 使用中的几个问题
    一、切换源代码模式快捷键修改:文件---偏好设置---通用---高级设置---打开高级设置,会打开C:\Users\Administrator\AppData\Roaming\Typora\conf目录,打开里面的conf.user.json文件,在keyBinding属性下,添加"源代码模式":"Ctrl+`",即可修改快捷键。二、编辑界面两边的空白:源......
  • OpenCV中表示图像的类Mat在QT里的基本使用
    在Qt中使用OpenCV的Mat类来表示和处理图像是相对简单的,因为Qt和OpenCV都是跨平台的,并且可以很好地在一起工作。以下是如何在Qt项目中使用OpenCV的Mat类的基本步骤:1.在Qt代码中包含OpenCV头文件在Qt的源代码文件中,你需要包含OpenCV的头文件以及opencv统一的命名空间来使用Mat......
  • 使用Spring管理Bean(一)
    一、IOC和DI1、简介IOC是InversionOfControl(控制反转)的缩写,它是一种设计思想,是指将对象的控制权由程序代码反转给外部容器。publicclassAccountServiceImplimplementsIAccountService{privateIAccountDaoaccountDao;publicAccoutServiceImpl({......
  • 使用open3d分离背景和物体点云(二)
    一、代码Pythonimportcv2importopen3daso3dimportmatplotlib.pyplotaspltimportnumpyasnpdefthPlaneSeg(pointcloud):pcd_np=np.asarray(pointcloud.points)#设置深度阈值(假设Z轴是深度轴)depth_threshold=0.196#1.0米#应......
  • Python实战:使用Python进行Faces聚类
    1.引言Faces聚类是一种基于人脸图像的聚类算法,它可以将相似的人脸图像分组在一起,从而实现对大规模人脸图像库的分类和识别。通过Python实现Faces聚类,我们可以加深对编程语言的理解,同时也能够体会到编程带来的便利。2.环境准备在开始编写Faces聚类系统之前,我们需......
  • 第11章 使用类——再谈重载:矢量类(一)
    本文章是作者根据史蒂芬·普拉达所著的《C++PrimerPlus》而整理出的读书笔记,如果您在浏览过程中发现了什么错误,烦请告知。另外,此书由浅入深,非常适合有C语言基础的人学习,感兴趣的朋友可以自行阅读此书籍。矢量,是工程和物理中使用的一个术语,它是一个有大小和方向的量。例如,推东......