单向链表入门指南:从零开始理解数据结构基础
一、简介和应用
单向链表是一种基础的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。与数组不同,链表中的元素在内存中不是连续存储的,而是通过指针链接在一起。
应用场景:
单向链表特别适合需要频繁插入和删除操作的场景,因为它的时间复杂度是O(1),而数组在这些操作上通常是O(n)。
二、特点和注意事项
特点:
1.动态大小:链表可以根据需要动态增长或缩小
2.高效插入/删除:在已知位置插入或删除节点非常高效
3.内存利用率:不需要预先分配连续内存空间
4.实现简单:基本操作逻辑清晰易懂
注意事项:
1.访问效率:随机访问效率低,需要从头遍历
2.内存开销:每个节点需要额外空间存储指针
3.边界条件:处理头节点和尾节点时需要特别注意
4.内存管理:需要手动管理节点的内存分配和释放
5.循环引用:注意避免形成循环链表(除非有意为之)
三、实现步骤解析
1.定义节点结构:创建包含数据和next指针的结构体
2.初始化链表:创建头节点作为链表的起点
3.实现基本操作:
添加节点:遍历到链表末尾并添加新节点
插入节点:找到指定位置并调整指针
删除节点:绕过要删除的节点并释放内存
修改节点:定位到指定节点并修改数据
查询节点:遍历到指定位置并返回数据
4.实现反转功能:
四、完整代码和注释
#include<iostream> using namespACe std; // 定义链表节点结构体 struct node { int data=0; // 节点存储的数据,默认为0 node* next=nullptr; // 指向下一个节点的指针,默认为空 }; // 定义链表类 class linklist { public: node* head=new node; // 创建头节点 // 在链表末尾添加新节点 void add(int data) { node* tmp = head; // 从头节点开始 while (tmp->next != nullptr) // 遍历到最后一个节点 { tmp = tmp->next; } node* datanode = new node; // 创建新节点 datanode->data = data; // 设置新节点数据 tmp->next = datanode; // 将新节点链接到链表末尾 } // 在指定位置插入新节点 void insert(int data, int idx) { node* datanode = new node; // 创建新节点 datanode->data = data; // 设置新节点数据 node* tmp = head; // 从头节点开始 for (int i = 0;i < idx;i++) // 移动到要插入位置的前一个节点 { tmp = tmp->next; } datanode->next = tmp->next; // 新节点指向原位置节点 tmp->next = datanode; // 前一个节点指向新节点 } // 删除指定位置的节点 void deleteNode(int idx) { node* tmp = head; // 从头节点开始 for (int i = 0;i < idx;i++) // 移动到要删除位置的前一个节点 { tmp = tmp->next; } tmp->next = tmp->next->next; // 绕过要删除的节点 // 注意:这里应该释放被删除节点的内存 } // 修改指定位置节点的数据 void change(int data, int idx) { node* tmp = head; // 从头节点开始 for (int i = 0;i <= idx;i++) // 移动到目标节点 { tmp = tmp->next; } tmp->data = data; // 修改节点数据 } // 查询指定位置节点的数据 int select(int idx) { node* tmp = head; // 从头节点开始 for (int i = 0;i <= idx;i++) // 移动到目标节点 { tmp = tmp->next; } return tmp->data; // 返回节点数据 } // 递归方式反转链表 node* reverse(node* head) { // 基本情况:空链表或只有一个节点 if (head == nullptr or head->next == nullptr) { return head; } // 递归反转剩余部分 node* newHead = reverse(head->next); // 将当前节点连接到反转后的链表末尾 head->next->next = head; head->next = nullptr; // 更新头节点指针 linklist::head->next = newHead; return newHead; } // 迭代方式反转链表 node* otherReverse(node* head) { node* a = head; // 前一个节点指针 node* b = a->next; // 当前节点指针 a->next = nullptr; // 第一个节点变为最后一个节点 while (b) // 遍历整个链表 { node* tmp = b->next; // 保存下一个节点 b->next = a; // 反转指针方向 a = b; // 移动a指针 b = tmp; // 移动b指针 } // 更新头节点指针 linklist::head->next = a; return a; } };
五、总结
单向链表是学习数据结构的绝佳起点,它帮助我们理解指针操作和动态内存管理的基本概念。本文通过一个完整的C++实现,展示了链表的基本操作和两种反转方法。对于初学者来说,理解链表的工作原理将为学习更复杂的数据结构(如双向链表、树、图等)打下坚实基础。
原创内容 转载请注明出处