当前位置: 首页 > news >正文

线性表之链表的介绍和使用

文章目录

    • 一、什么是单链表
      • 1.1 单链表的节点插入
      • 1.2 单链表的节点删除
      • 1.3 单链表的节点释放
      • 1.4 单链表的搜索
      • 1.5 单链表的逆序
      • 1.6 输出单链表倒数第k个节点

一、什么是单链表

单链表(Singly Linked List) 是一种线性数据结构,与数组类似,但它通过指针连接节点而不是连续的内存存储。每一个节点只能找到下一个节点,无法回退到上一个节点。

每个节点(Node)包含两部分:

  1. 数据域(data):存储节点的数据。
  2. 指针域(next):存储下一个节点的地址。

最后一个节点的 next 指针为 nullptr,表示链表结束。

单链表的示意图:
在这里插入图片描述

1.1 单链表的节点插入

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <string.h>// 节点类型
struct Node {int data_;Node* next_;Node(int data = 0) :data_(data),next_(nullptr) {}
};// 单链表代码实现
class Clink {
public: Clink() {// 给head_初始化指向头节点head_ = new Node();}~Clink() {// 节点的释放}public:// 链表的尾插法(特点:尾节点的地址域为nullptr) O(n)void InsertTail(int val) {// 先找到当前链表的末尾节点Node* p = head_;while (p->next_ != nullptr) {// 没有找到尾节点,继续p = p->next_;}// 生成新节点Node* node = new Node(val);// 把新节点挂在尾节点的后面p->next_ = node;}// 链表的头插法 O(1)void InsertHead(int val) {Node* node = new Node(val);node->next_ = head_->next_;head_->next_ = node;}// 链表打印void Show() {Node* p = head_->next_;while (p != nullptr) {std::cout << p->data_ << " ";p = p->next_;}std::cout << std::endl;}private:Node* head_; // 指向链表的头节点
};int main() {Clink link;srand(time(0));for (int i = 0; i < 10; i++) {int val = rand() % 100;link.InsertTail(val);std::cout << val << " ";}std::cout << std::endl;link.Show();
}

输出结果:
在这里插入图片描述

1.2 单链表的节点删除

// 链表节点的删除
void Remove(int val) {Node* q = head_;Node* p = head_->next_;while (p != nullptr) {if (p->data_ == val) {q->next_ = p->next_;delete p;return;} else {q = p;p = p->next_;}}
}

1.3 单链表的节点释放

// 释放节点
void freeNode() {Node* p = head_;while (p != nullptr) {head_ = head_->next_;delete p;p = head_;}
}

1.4 单链表的搜索

// 搜索 O(n)   
bool Find(int val) {Node* p = head_->next_;while (p != nullptr) {if (p->data_ == val) {return true;} else {p = p->next_;}}return false;
}

1.5 单链表的逆序

头插法(Head Insertion Method)是理解单链表反转最直观、最形象的一种方式。它不依赖复杂的指针反转逻辑,而是逐个节点“插到新表头”前面。

操作步骤
假设原链表如下:

head → [1][2][3][4]nullptr

我们准备一个空的新链表 newHead = nullptr,然后逐个把原链表的节点摘下来,插入到新链表的头部。

第 1 步
取出节点 [1]:

newHead = nullptr
head = [1][2][3][4]

操作:

node = head        // node 指向 [1]
head = head->next  // head 指向 [2]
node->next = newHead  // [1]->next = nullptr
newHead = node        // newHead = [1]

结果:

newHead → [1]nullptr
head → [2][3][4]

第 2 步
取出节点 [2]:

node = head        // node = [2]
head = head->next  // head = [3]
node->next = newHead  // [2]->next = [1]
newHead = node        // newHead = [2]

结果:

newHead → [2][1]nullptr
head → [3][4]

第 3 步
取出 [3] 插入头部:

newHead → [3][2][1]nullptr
head → [4]

第 4 步
取出 [4] 插入头部:

newHead → [4][3][2][1]nullptr
head → nullptr

循环结束,反转完成!

代码实现:

void printList(ListNode* head) {while (head) {cout << head->val;if (head->next) cout << " -> ";head = head->next;}cout << endl;
}ListNode* reverseListInsert(ListNode* head) {ListNode* newHead = nullptr;while (head) {ListNode* node = head;head = head->next;node->next = newHead;newHead = node;}return newHead;
}int main() {// 构建链表 1->2->3->4->5ListNode* head = new ListNode(1);head->next = new ListNode(2);head->next->next = new ListNode(3);head->next->next->next = new ListNode(4);head->next->next->next->next = new ListNode(5);cout << "原链表: ";printList(head);head = reverseListInsert(head);cout << "反转后: ";printList(head);
}

输出结果:
在这里插入图片描述
带头结点的单链表在头部有一个不存放有效数据的节点(即 head),它的作用是方便统一插入、删除操作。
代码示例:

#include <iostream>
using namespace std;struct ListNode {int data;ListNode* next;ListNode(int d = 0) : data(d), next(nullptr) {}
};// 头插法逆序(带头节点)
void ReverseList(ListNode* head) {ListNode* p = head->next; // 当前节点head->next = nullptr;     // 断开原链表while (p != nullptr) {ListNode* next = p->next; // 暂存后继节点p->next = head->next;     // 插入到头部head->next = p;           // 更新头指针p = next;                 // 处理下一个}
}// 打印链表
void PrintList(ListNode* head) {ListNode* p = head->next;while (p) {cout << p->data << " ";p = p->next;}cout << endl;
}int main() {// 构建带头节点的链表 head->1->2->3->4ListNode* head = new ListNode();ListNode* tail = head;for (int i = 1; i <= 4; ++i) {tail->next = new ListNode(i);tail = tail->next;}cout << "原链表: ";PrintList(head);ReverseList(head);cout << "逆序后: ";PrintList(head);return 0;
}

1.6 输出单链表倒数第k个节点

要找到单链表的倒数第 k 个节点,可以使用双指针(快慢指针) 技巧:

  1. 定义两个指针:fast 和 slow,都指向链表的头节点;
  2. 先让 fast 向前移动 k 步;
  3. 然后同时移动 fast 和 slow,直到 fast 到达链表末尾;
  4. 此时,slow 指向的节点就是倒数第 k 个节点。

假设链表如下:
在这里插入图片描述
我们要求输出倒数第 k = 2 个节点,即节点 [4]。

步骤一:初始化指针
在这里插入图片描述
将指针fast和slow同时指向头节点head

步骤二:让 fast 先走 k 步(k=2)
第 1 步:
slow指针保持不变,fase指针先向前走2步
在这里插入图片描述
第 2 步:
第一步结束之后,slow指针和fase指针同时向前走一步
在这里插入图片描述
从上述图中可以看出此时fast指针比slow指针多走了两步

步骤三:同时移动 fast 和 slow
每次 fast 和 slow 同时前进 1 步:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当 fast == nullptr 时,slow 就正好指向了 倒数第 2 个节点 [4]。

代码实现:

#include <iostream>
using namespace std;struct ListNode {int val;ListNode* next;ListNode(int x) : val(x), next(nullptr) {}
};// 获取倒数第k个节点
ListNode* getKthFromEnd(ListNode* head, int k) {if (!head || k <= 0) return nullptr;ListNode* fast = head;ListNode* slow = head;// fast先走k步for (int i = 0; i < k; ++i) {if (!fast) return nullptr; // 链表长度小于kfast = fast->next;}// 同时移动 fast 和 slowwhile (fast) {fast = fast->next;slow = slow->next;}return slow;
}int main() {// 构建链表 1->2->3->4->5ListNode* head = new ListNode(1);head->next = new ListNode(2);head->next->next = new ListNode(3);head->next->next->next = new ListNode(4);head->next->next->next->next = new ListNode(5);int k = 2;ListNode* node = getKthFromEnd(head, k);if (node)cout << "倒数第 " << k << " 个节点的值是: " << node->val << endl;elsecout << "链表长度小于 " << k << endl;return 0;
}

输出结果:
在这里插入图片描述

http://www.dtcms.com/a/574939.html

相关文章:

  • 企业网站管理系统螺栓球网架
  • 做的网站在百度找不到wordpress更换皮肤
  • 网络传输协议的介绍——SSE
  • 河南省建设厅网站 吴浩浙江省建设执业注册中心网站
  • 桂林网站客户管理系统免费
  • 基于ssm的实验室耗材管理系统
  • wordpress做分类信息网站东莞市住建局官网
  • Rust 练习册 4:Deref trait 与智能指针
  • 8.【NXP 号令者RT1052】开发——实战-外部中断
  • 国内出名的设计网站有哪些老网站做seo能不能重新注册
  • ETL 清洗在某平台中的概念与实践解析
  • obsidian1.9.14_win中文_Markdown编辑器_安装教程
  • 网站建设财务怎么入账的wordpress主题
  • yaml配置文件和语法说明
  • 成都网站建设 天空在线wordpress机械模板下载
  • 广州公司制作网站小型网站建设步骤
  • 致同研究:附有质量保证条款的销售的披露示例
  • 建设部网站官网景德镇建设网站
  • 网站建设制作设计惠州七牛云wordpress缓存配置
  • 外贸网站建设制作Windows怎么建设网站
  • 虹桥做网站公司网站制作手机
  • 网站ww正能量嘉兴网站制作厂家
  • 面向强化学习的状态空间建模:RSSM的介绍和PyTorch实现
  • 10.2 一种融合深度空间特征增强与注意力去噪的新型 3D 室内定位方法研究总结
  • 理解PostgreSQL中的CMIN和CMAX
  • 使用 PostgreSQL 时间点恢复(Point-In-Time Recovery)的多种数据恢复技术
  • 营销网站制作教程微信表情开放平台官网
  • 调控大肠杆菌胞内ATP和NADH水平促进琥珀酸生产--文献精读172
  • Spring-cloud 主键Nacos
  • 网站开发尺寸外贸做的亚马逊网站是哪个