一、单链表
特点:
- 每一个节点都是在堆内存上独立new出来的,节点内存不连续
- 每一个节点除了数据域,还有一个next指针域指向下一个节点(存储了下一个节点的地址),但是无法回退到前一个节点
- 末尾节点的指针域是NULL
优点
- 内存利用率高,不需要大块连续内存
- 插入和删除节点不需要移动其它节点,时间复杂度O(1)
- 不需要专门进行扩容操作
二、代码实现
1.接口和初始化链表
代码如下(示例):
定义:
struct Node
{
Node(int data=0):data_(data),next_(nullptr){}
int data_;
Node* next_;
};
初始化以及接口
class Clink
{
public:
Clink()
{
//给head_初始化指向头节点
head_ = new Node();
}
~Clink()
{
//节点的释放
Node* p = head_;
while (p != nullptr)
{
head_ = head_->next_;
delete p;
p = head_;
}
head_ = nullptr;
}
public:
//链表尾插法 O(n)
void InsertTail(int val);
//链表的头插法 O(1)
void InsertHead(int val);
//链表节点的删除
void Remove(int val);
//删除多个节点
void RemoveAll(int val);
//搜索
bool Find(int val);
//链表打印
void Show();
private:
Node* head_;//指向链表的头结点
};
2.完整代码
代码如下(示例):
#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;
//节点类型
struct Node
{
Node(int data=0):data_(data),next_(nullptr){}
int data_;
Node* next_;
};
//单链表代码实现
class Clink
{
public:
Clink()
{
//给head_初始化指向头节点
head_ = new Node();
}
~Clink()
{
//节点的释放
Node* p = head_;
while (p != nullptr)
{
head_ = head_->next_;
delete p;
p = head_;
}
head_ = nullptr;
}
public:
//链表尾插法 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 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_;
}
}
}
//删除多个节点
void RemoveAll(int val)
{
Node* q = head_;
Node* p = head_->next_;
while (p != nullptr)
{
if (p->data_ == val)
{
q->next_ = p->next_;
delete p;
//对指针p进行重置
p = q->next_;
}
else
{
q = p;
p = p->next_;
}
}
}
//搜索 list O(n) 数组的搜索 下表访问/随机访问arr[i]O(1) 搜索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;
}
//链表打印
void Show() {
Node* p = head_->next_;
while (p != nullptr)
{
cout << p->data_ << " ";
p = p->next_;
}
cout << endl;
}
private:
Node* head_;//指向链表的头结点
};
int main() {
Clink link;
srand(time(0));
for (int i = 0; i < 10; i++)
{
int val = rand() % 100;
link.InsertHead(val);
cout << val<<" ";
}
cout << endl;
link.InsertHead(200);
link.InsertHead(23);
link.InsertHead(45);
link.InsertHead(23);
link.Show();
link.RemoveAll(23);
link.Show();
return 0;
}
总结
今天主要给大家介绍了C++单链表各个接口的实现,以及单链表的优缺点和特点,希望大家在面试中能有所用。