链表 Linked List
2024.3.15
芝士wa
参考视频:bilibli-数据结构-链表 “印度小哥讲得真好”
链表
- 对于链表来说,存储数据需要两个部分,一是数据本身,二是指针,该指针指向下一个数据的地址,依次链接,直到最后一个元素,指针指向空(NULL)
-
遍历的时间复杂度为O(n)
-
插入的时间复杂度为O(n)
-
删除的时间复杂度为O(n)
链表VS数组
-
数组是连续存储空间,链表通过指针维系,存储数据并不连续
-
数组可以通过下标访问元素,只需要O(1)的时间复杂度,而链表则必须按照顺序访问,因此时间复杂度为O(n/2) = O(n)
-
数组的大小是固定的,在创建数组时确认
-
优势:链表在添加或删除元素时,避免了不相关元素的复制移动,空间复杂度较小
-
使用链表时,要格外注意指针问题
链表的C++实现
完整代码
#pragma once
#include <iostream>
using namespace std;
template<class T>
class Node
{
public:
T data;
Node* next;
};
template<class T>
class LinkedList
{
public:
LinkedList();
~LinkedList();
Node<T>* head;
int m_num;//记录节点个数
//尾插法
void Insert(T x);
//在特定位置添加
void Insert(T x, int n);
//打印,遍历法
void print();
//递归方法打印
void Rprint(Node<T>* p);
//特定位置删除
void remove(int n);
//反转链表,迭代法
void reverse();
//反转链表,递归方法
void Reverse(Node<T>* p);
};
template<class T>
LinkedList<T>::LinkedList()
{
head = new Node<T>;
head->next = NULL;
this->m_num = 0;
}
template<class T>
LinkedList<T>::~LinkedList()
{
Node<T>* ite = head;
Node<T>* next;
while (ite != NULL) {
next = ite->next;
delete ite;
ite = next;
}
this->m_num = 0;
}
template<class T>//尾插法添加元素
void LinkedList<T>::Insert(T x)
{
Node<T>* end = new Node<T>;
end->data = x;
end->next = NULL;
if (head== NULL) {
//链表为空
head = end;
this->m_num++;
cout << "添加成功,当前节点数量:" << this->m_num << endl;
}
else {
Node<T>* ite = head;
//链表不为空,得到末尾end
while (ite->next != NULL) {
ite = ite->next;
}
//现在ite指向最后一个元素
ite->next = end;
}
this->m_num++;
cout << "添加成功,当前节点数量:" << this->m_num << endl;
}
template<class T>//特定位置添加元素
void LinkedList<T>::Insert(T x, int n)
{
Node<T>* temp = new Node<T>;
temp->data = x;
temp->next = NULL;
if (n == 1) {
//在头节点之后添加
temp->next = head->next;
head = temp;
this->m_num++;
cout << "添加成功,当前节点数量:" << this->m_num << endl;
return;
}
else if(n > 1 && n <= this->m_num){
Node<T>* ite = head;
//找到第n-1个元素,
for (int i = 0; i <= n - 2; i++) {
ite = ite->next;
}
temp->next = ite->next;
ite->next = temp;
this->m_num++;
cout << "添加成功,当前节点数量:" << this->m_num << endl;
return;
}
else {
cout << "越界" << endl;
return;
}
}
template<class T>
void LinkedList<T>::print()
{
Node<T>* ite = head;
while (ite!= NULL) {
cout << ite->data << "\t";
ite = ite->next;
}
cout << endl;
}
template<class T>
void LinkedList<T>::Rprint(Node<T> * p)
{
if (p == NULL) {
return;
}
Rprint(p->next);
cout << p->data << "\t";
}
template<class T>
void LinkedList<T>::remove(int n)
{
Node<T>* temp = head;
//第一个节点
if (n == 1) {
head = head->next;
delete temp;
this->m_num--;
cout << "删除成功,当前节点数量:" << this->m_num << endl;
return;
}
//第2~num之间删除节点
else if (n > 1 && n <= this->m_num) {
for (int i = 0; i < n - 2; i++) {
temp = temp->next;
}
//现在temp指向的是第n-1个节点
Node<T>* temp1 = temp->next;//指向第n个
temp->next = temp1->next;
delete temp1;
this->m_num--;
cout << "删除成功,当前节点数量:" << this->m_num << endl;
return;
}
else {
cout << "越界" << endl;
return;
}
}
template<class T>
void LinkedList<T>::reverse()
{
Node<T>* current, * prev, * next;
current = head;
prev = NULL;
while (current != NULL) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
head = prev;
}
template<class T>
void LinkedList<T>::Reverse(Node<T>* p)
{
if (p->next == NULL) {
head = p;
return;
}
Reverse(p->next);
p->next->next = p;
p->next = NULL;
}
- 模板,泛型
- 内部维护链表长度
- 分别用递归和迭代的方式实现了打印和反转
- 进行了简单的越界判断处理
双向链表
template<class T>
class Node
{
T data;
Node* prev;
Node* next;
};
总结
本文介绍了链表的概念和特性,并用C++实现了单链表。
本文来自博客园,作者:芝士wa,转载请注明原文链接:https://www.cnblogs.com/cheese-wa/p/18076041