首页 > 编程语言 >编程导航算法通关村第 1 关 | 链表

编程导航算法通关村第 1 关 | 链表

时间:2023-10-22 23:25:00浏览次数:38  
标签:head ListNode 编程 next 链表 n0 节点 通关

1. 前置知识补充

内容引用:https://www.hello-algo.com/

数据结构

数据结构如同一副稳固而多样的框架。

它为数据的有序组织提供了蓝图,使算法得以在此基础上生动起来。

分类

1. 根据逻辑类型分类

逻辑结构揭示了数据元素之间的逻辑关系。在数组和链表中,数据按照顺序依次排列,体现了数据之间的线性关系;而在树中,数据从顶部向下按层次排列,表现出祖先与后代之间的派生关系;图则由节点和边构成,反映了复杂的网络关系。

img

  • 线性数据结构:数组、链表、栈、队列、哈希表。
  • 非线性数据结构:树、堆、图、哈希表。

2. 根据物理结构分类

根据物理结构可以分为连续和分散的

连续空间存储与分散空间存储

值得说明的是,所有数据结构都是基于数组、链表或二者的组合实现的。例如,栈和队列既可以使用数组实现,也可以使用链表实现;而哈希表的实现可能同时包含数组和链表。

  • 基于数组可实现:栈、队列、哈希表、树、堆、图、矩阵、张量(维度 ≥3 的数组)等。
  • 基于链表可实现:栈、队列、哈希表、树、堆、图等。

基于数组实现的数据结构也被称为“静态数据结构”,这意味着此类数据结构在初始化后长度不可变。相对应地,基于链表实现的数据结构被称为“动态数据结构”,这类数据结构在初始化后,仍可以在程序运行过程中对其长度进行调整。

2. 链表

「链表 linked list」是一种线性数据结构,其中的每个元素都是一个节点对象,各个节点通过“引用”相连接。引用记录了下一个节点的内存地址,通过它可以从当前节点访问到下一个节点。

2.1 链表的定义

/* 链表节点类 */
class ListNode {
    int val;        // 节点值
    ListNode next;  // 指向下一节点的引用
    ListNode(int x) { val = x; }  // 构造函数
}

2.2 单链表的操作

1. 初始化链表

建立链表分为两步,第一步是初始化各个节点对象,第二步是构建引用指向关系。初始化完成后,我们就可以从链表的头节点出发,通过引用指向 next 依次访问所有节点。

/* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */
// 初始化各个节点
ListNode n0 = new ListNode(1);
ListNode n1 = new ListNode(3);
ListNode n2 = new ListNode(2);
ListNode n3 = new ListNode(5);
ListNode n4 = new ListNode(4);
// 构建引用指向
n0.next = n1;
n1.next = n2;
n2.next = n3;
n3.next = n4;

2. 插入节点

在链表中插入节点非常容易。如图 4-6 所示,假设我们想在相邻的两个节点 n0n1 之间插入一个新节点 P则只需要改变两个节点引用(指针)即可,时间复杂度为 O(1) 。

相比之下,在数组中插入元素的时间复杂度为 O(n) ,在大数据量下的效率较低。

链表插入节点示例

/* 在链表的节点 n0 之后插入节点 P */
void insert(ListNode n0, ListNode P) {
    ListNode n1 = n0.next;
    P.next = n1;
    n0.next = P;
}
3. 删除节点

在链表中删除节点也非常方便,只需改变一个节点的引用(指针)即可

请注意,尽管在删除操作完成后节点 P 仍然指向 n1 ,但实际上遍历此链表已经无法访问到 P ,这意味着 P 已经不再属于该链表了。

链表删除节点

/* 删除链表的节点 n0 之后的首个节点 */
void remove(ListNode n0) {
    if (n0.next == null)
        return;
    // n0 -> P -> n1
    ListNode P = n0.next;
    ListNode n1 = P.next;
    n0.next = n1;
}
4. 访问节点

在链表访问节点的效率较低。我们可以在O(1) 时间下访问数组中的任意元素。链表则不然,程序需要从头节点出发,逐个向后遍历,直至找到目标节点。也就是说,访问链表的第 i 个节点需要循环 i −1 轮,时间复杂度为 O(n) 。

PythonC++JavaC#GoSwiftJSTSDartRustCZig

linked_list.java

/* 访问链表中索引为 index 的节点 */
ListNode access(ListNode head, int index) {
    for (int i = 0; i < index; i++) {
        if (head == null)
            return null;
        head = head.next;
    }
    return head;
}
5. 查找节点

遍历链表,查找链表内值为 target 的节点,输出节点在链表中的索引。此过程也属于线性查找。

/* 在链表中查找值为 target 的首个节点 */
int find(ListNode head, int target) {
    int index = 0;
    while (head != null) {
        if (head.val == target)
            return index;
        head = head.next;
        index++;
    }
    return -1;
}

3. 问题

1.链表增加元素,首部、中间和尾部分别会有什么问题,该如何处理?

  • 首部

    • 问题:在链表的首部添加元素可能导致原来的首节点被替换,从而丢失对原始首节点的引用。

    • 处理方法:可以创建一个新的节点,并将其设置为新的首节点。新节点的下一个节点将指向原始首节点,从而保留对原始首节点的引用。(将新的头部和原有头部分开保存)

    • 问题: 经常会忘了head需要重新指向表头

    • 解决方法: 将head重新指向newNode

  • 中间

    • 问题:在链表的中间位置添加元素会涉及节点的重新连接,需要确保插入节点的前一个节点和后一个节点正确连接,否则会导致数据丢失或链表断裂。
    • 处理方法:可以按照以下步骤处理中间添加元素:
      • 创建一个新节点,并将要插入的元素存储在新节点中。
      • 找到要插入的位置的前一个节点。
      • 将新节点的下一个节点设置为前一个节点的下一个节点。
      • 将前一个节点的下一个节点设置为新节点。

标签:head,ListNode,编程,next,链表,n0,节点,通关
From: https://www.cnblogs.com/ks2022/p/17781362.html

相关文章

  • 编程探索队团队介绍
    编程探索队队员介绍20211310何威烨(组长):我是个有条理、注重细节的人,具有创造性思维。我兴趣广泛,对软件开发、网络安全和前端或后端开发等方面都有粗略的了解。希望在接下来的合作中,我能不断解决复杂问题或挑战,不断学习并探索新的编程技术和工具。在项目中,在项目中,我希望参与需......
  • 实验2 类和对象_基础编程2
    //第一个任务简单Complex类#pragmaonce#include<iostream>#include<cmath>classComplex{public:Complex(doublex0=0,doubley0=0);//构造函数Complex(constComplex&c);//拷贝构造函数~Complex(){};//析构函数doubleget_real()con......
  • 实验2 类和对象_基础编程2
    1.实验任务3程序代码组织如下:•Complex.h类Complex的声明#pragmaonce#include<iostream>#include<cmath>classComplex{public:Complex(doubler=0,doublei=0);Complex(constComplex&c);~Complex(){};doubleget_real()cons......
  • 实验2 c语言分支与循环基础应用编程
    task11#include<stdio.h>2#include<stdlib.h>3#include<time.h>45#defineN56#defineN13747#defineN246589intmain()10{11intnumber;12inti;13srand(time(0));//以当前系统时间作为随机种子14for(i=0;i<N;......
  • 实验2_C语言分枝与循环基础应用编程
    试验任务1task1.c#include<stdio.h>#include<stdlib.h>#include<time.h>#defineN5#defineN1374#defineN2465intmain(){intnumber;inti;srand(time(0));for(i=0;i<N;++i){number=r......
  • 高性能处理器架构与编程(一)
    引言:云-端-边协同:同构协同(ARM、具体实例为鲲鹏)同操作系统(Vela,在物联网侧的统一)课时安排鲲鹏920和ARM处理器架构介绍(第一周)鲲鹏处理器基础实验(10课时)(第二、三周)鲲鹏处理器系统实验(8课时)(第四、五周)应用编程实验(8课时)上午华为海思的产品系列通用计算处理器:鲲鹏手机应用处......
  • 面试必刷TOP101:9、删除链表的倒数第n个节点
    一、题目二、题解2.1双指针由于我们需要找到倒数第n个节点,因此可以使用两个指针fast和slow同时对链表进行遍历,并且fast比slow超前n个节点。当fast遍历到链表的末尾时,slow就恰好处于倒数第n个节点。具体地,初始时fast和slow均指向头节点。首先使用fast对链表......
  • QT-多窗口程序编程
    exec()解析引用参考:qt中main函数中的exec()作用总结_qtexec-CSDN博客intmain(intargc,char*argv[]){ QApplicationa(argc,argv);MainWindoww;w.show();returna.exec(); //出现在此处}main函数的返回直接交由系统(更底层)进行处理,exec的作用则确定与......
  • 编程学习思考
    编程学习的思考2023-10-2114:50:29星期六(初稿)大家好!自从大一开始进入计算机科学与技术专业学习,便就开始踏入编程的学习之旅。又是一个秋季,整整三年了!三年以来,自然是有不少成长,现在回想,这一路中也遇到很多的挫折,也受到过许多”愚蠢“的思想的影响···,跌跌撞撞地前行,当然在这......
  • 08_面向对象编程(高级)
    ......