首页 > 其他分享 >2 链表

2 链表

时间:2023-07-19 16:44:23浏览次数:24  
标签:ListNode cur fast next 链表 节点

# 链表
## 1 链表基础理论 什么是链表,链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。
链表的入口节点称为链表的头结点也就是head。 - 单链表 ![img](/i/l/?n=23&i=blog/3237570/202307/3237570-20230719163639794-1068736237.png) - 双链表 ![img](/i/l/?n=23&i=blog/3237570/202307/3237570-20230719163648866-179426648.png) - 循环链表 <div align="center"> <img src="/i/l/?n=23&i=blog/3237570/202307/3237570-20230719163657608-1932348447.png" width = 200 /> </div>
链表在内存中不是连续分布的,是通过指针串联在一起的
链表的定义 ```C++ struct ListNode{     int val;     ListNode *next = nullptr;     ListNode(int x) : val(x), next(nullptr); }; ```
性能分析
||插入/删除(时间复杂度)|查询(时间复杂度)|适用场景| |:-:|:-:|:-:|:-:| |数组|O(n)|O(1)|数据量固定,频繁查询,较少增删| |链表|O(1)|O(n)|数据量不固定,频繁增删,较少查询|

## 2一处链表元素 [**力扣题目链接**](https://leetcode.cn/problems/remove-linked-list-elements/)
### 题目: 题意:删除链表中等于给定值 val 的所有节点。
示例 1: 输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]
示例 2: 输入:head = [], val = 1 输出:[]
示例 3: 输入:head = [7,7,7,7], val = 7 输出:[]
### 思路: 使用虚拟头节点dummy node
### 代码: ```C++ class Solution { public:     struct ListNode{         int val;         ListNode* next =nullptr;         ListNode(x): val(x),next(nullptr);     };     ListNode* removeElements(ListNode* head, int val) {         ListNode* dummyNode = new ListNode(0);         dummyNode->next = head;         ListNode* cur = dummyNode;         while (cur->next != NULL){             if(cur->next->val == val){                 ListNode* temp = cur->next;                 cur->next = cur->next->next;                 delete temp;             }else{                 cur = cur->next;             }                       }         return dummyNode->next;     } };   ```
## 3 设计链表
[**力扣题目链接**](https://leetcode.cn/problems/design-linked-list/)
### 题目: 在链表类中实现这些功能:
- get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。 - addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。 - addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。 - addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val  的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。 - deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。
### 思路: 这道题目设计链表的五个接口:
- 获取链表第index个节点的数值 - 在链表的最前面插入一个节点 - 在链表的最后面插入一个节点 - 在链表第index个节点前面插入一个节点 - 删除链表的第index个节点
同样使用虚拟头节点dummyHead
### 代码: ```C++ class MyLinkedList { public:     struct LinkedNode{         int val;         LinkedNode* next;         LinkedNode(int x): val(x), next(nullptr){}     };
    MyLinkedList() {         _dummyhead = new LinkedNode(0);         _size = 0;     }         int get(int index) {         if (index > (_size - 1) || index < 0) {             return -1;         }         LinkedNode* cur=_dummyhead->next;         while(index--){             cur = cur->next;         }         return cur->val;     }         void addAtHead(int val) {         LinkedNode* cur = new LinkedNode(val);         cur->next = _dummyhead->next;         _dummyhead->next = cur;         _size++;     }         void addAtTail(int val) {         LinkedNode* newNode = new LinkedNode(val);         LinkedNode* cur = _dummyhead;         while(cur->next!=nullptr){             cur = cur->next;         }         cur->next = newNode;         _size++;     }         void addAtIndex(int index, int val) {         LinkedNode* cur = _dummyhead;         //if(index<0) index =0;         if(_size < index) return;         while(index--){             cur = cur->next;         }         LinkedNode* tmp = cur->next;         cur->next = new LinkedNode(val);         cur->next->next = tmp;         _size++;     }         void deleteAtIndex(int index) {         LinkedNode* cur = _dummyhead;         if(_size <= index || index < 0) return;         while(index--){             cur = cur->next;         }         LinkedNode* tmp = cur->next;         cur->next = cur->next->next;         delete tmp;         tmp=nullptr;         _size--;     } private:     int _size;     LinkedNode* _dummyhead; }; ```
## 4 翻转链表
[**力扣题目链接**](https://leetcode.cn/problems/reverse-linked-list/)
### 题目: 题意:反转一个单链表。
示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL
### 思路:
双指针法,一个slow保存当前指针,一个fast保存下一个指针,再定义一个临时指针tmp保存fast指针的下一个节点,挨个反转即可(fast->next=slow)
### 代码: ```C++ ListNode* reverseList(ListNode* head) {     ListNode *slow = nullptr;     ListNode *fast = head;     ListNode *tmp;     if(head == nullptr) return nullptr;     while(fast != nullptr){         tmp = fast->next;         fast->next=slow;         slow = fast;         fast = tmp;     }     return slow; } ```

## 5 两两交换链表中的节点
[**力扣题目链接**](https://leetcode.cn/problems/swap-nodes-in-pairs/)
### 题目: 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
### 思路: 模拟过程,以三步一个循环,主要注意边界条件,
### 代码: ```C++ ListNode* swapPairs(ListNode* head) {     ListNode* dummyHead = new ListNode(0);     dummyHead->next = head;     ListNode* cur = dummyHead;     while(cur->next!=nullptr&&cur->next->next!=nullptr){         ListNode*tmp1 = cur->next;         ListNode*tmp2 = cur->next->next->next;
        cur->next = cur->next->next;         cur->next->next = tmp1;         cur->next->next->next = tmp2;
        cur = cur->next->next;     }     return dummyHead->next; } ```

## 6 删除链表的倒数第N个节点
[**力扣题目链接**](https://leetcode.cn/problems/remove-nth-node-from-end-of-list/submissions/)
### 题目:
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
### 思路:
虚拟头节点+双指针,计数fast指针计数n后slow指针再动,终止条件fast为空。
### 代码: ```C++ ListNode* removeNthFromEnd(ListNode* head, int n) {     ListNode *dummyhead = new ListNode(0);     dummyhead -> next = head;     ListNode*fast=dummyhead;     ListNode*slow=dummyhead;     while(n--){         fast = fast->next;     }     while(fast->next!=nullptr){         fast=fast->next;         slow=slow->next;     }     slow->next=slow->next->next;     return dummyhead->next; } ```

## 7 链表相交
[**力扣题目链接**](https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/)
### 题目: 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。 ### 思路: 相交节点,注意是指针相同,注意相交一定在某一个交点后完全相同,先求得两个链表的长度,假设长度n1>=n2,然后将较长的链表移动n1-n2步,判断与较短链表头节点是否相等
### 代码: ```C++ ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {     ListNode *curA = headA;     ListNode *curB = headB;     int lengthA = 0;     int lengthB = 0;     while(curA != NULL){         lengthA++;         curA = curA->next;     }     while(curB != NULL){         lengthB++;         curB = curB->next;     }     int lengthNum;     if(lengthA < lengthB){         swap(lengthA,lengthB);         curA = headB;         curB = headA;     }     else{         curA = headA;         curB = headB;     }     lengthNum = lengthA - lengthB;     while(lengthNum--){         curA = curA->next;     }     while(curA!= NULL){         if(curA== curB) return curA;         curB = curB->next;         curA = curA->next;     }     return NULL; } ```

## 8 环形链表Ⅱ
[**力扣题目链接**](https://leetcode.cn/problems/linked-list-cycle-ii/)
### 题目: 题意: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
### 思路: 可以使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。且通过公式计算可以得到fast与head同时后移到相遇的位置就是环的入口。
### 代码: ```C++ ListNode *detectCycle(ListNode *head) {     ListNode *fast = head;     ListNode *slow = head;     while(fast!=NULL && fast->next!=NULL){         fast=fast->next->next;         slow =slow->next;         if(fast == slow){             ListNode *node1 = head;             ListNode *node2 = fast;             while(node1!=node2){                 node1=node1->next;                 node2=node2->next;             }             return node2;         }     }     return NULL; } ```

标签:ListNode,cur,fast,next,链表,节点
From: https://www.cnblogs.com/mobbu/p/17566034.html

相关文章

  • 剑指offer--链表
    第6题:链表中倒数最后k个结点题目描述输入一个长度为n的链表,设链表中的元素的值为\(a_i\),返回该链表中的第k个结点。如果该链表长度小于\(k\),请返回一个长度为0的链表思路双指针step1:准备一个快指针,从链表头开始,在链表上先走k步。step2:准备慢指针指向原始链表头,代......
  • 单链表快速排序
    title:单链表快速排序date:2023-07-1809:06:37tags:-c/c++categories:-算法-笔试top:单链表快速排序题目来自acwing题目(点击跳转)给定一个单链表,请使用快速排序算法对其排序。要求:期望平均时间复杂度为O(nlogn),期望额外空间复杂度为O(logn)。思考题:如果只能......
  • 数据结构练习笔记——删除单链表中相同元素
    删除单链表中相同元素【问题描述】单链表中存放了若干整数,请删除相同整数。【输入形式】单链表【输出形式】删除相同整数后的单链表【样例输入】11123【样例输出】123【样例说明】递增的形式输入数据,允许相同元素#include<stdlib.h>#include<iostream>usingname......
  • day3 链表封装
    封装链表:  1、单链表    由于不封装链表结构时,链表的尾添加效率低    其次非法位置的判断效率也很低,只能遍历来判断    节点:      数据域data      指针域next    链表结构:      头指针  ......
  • LeetCode 热题 100 之 160. 相交链表
    题目描述给你两个单链表的头节点 headA和headB,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回null。图示两个链表在节点c1开始相交:题目数据保证整个链式结构中不存在环。注意,函数返回结果后,链表必须保持其原始结构。自定义评测:评测......
  • 反转链表
    `/**Definitionforsingly-linkedlist.structListNode{intval;structListNode*next;};*/structListNode*reverseList(structListNode*head){structListNode*newhead=NULL,tmp;while(head){/tmp=head->next;head->next=newhead;......
  • 用java写一个逆置单链表
    用Java写一个逆置单链表单链表是一种常见的数据结构,它由一系列节点组成,每个节点包含一个数据元素和一个指向下一个节点的引用。逆置单链表是指将原来的单链表中的节点顺序颠倒过来。在这篇文章中,我们将使用Java来实现逆置单链表的功能。我们将会介绍单链表的基本概念,并给出逆置单......
  • 用java创建一个单链表
    使用Java可以很方便地创建和操作数据结构,其中包括单链表。单链表是一种常见的线性数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。这种数据结构可以用于实现队列、栈、链表等等。在本文中,我们将学习如何使用Java创建一个单链表,并演示一些基本的操作。首先,我......
  • 数据结构练习笔记——创建有序单链表
    创建有序单链表【问题描述】为从键盘终端输入的m个整数创建带头结点的有序单链表存储结构,使输入的数据元素在单链表中按照元素值递增有序。【输入形式】第一行:单链表中元素个数m第二行:单链表中的m个整数【输出形式】按递增有序形式输出m个整数【样例输入】513245【......
  • Java性能优化-测试数组和链表在查询和添加删除时性能对比
    场景Java中使用JMH(JavaMicrobenchmarkHarness微基准测试框架)进行性能测试和优化:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/131723751上面在使用JMH时测试了Java中数组和链表在进行头部插入时的对比结果。下面分别对比在头部、中部、尾部分别进行查询和......