从C语言到C++_17(list的模拟实现)list不是原生指针的迭代器

简介: 从C语言到C++_17(list的模拟实现)list不是原生指针的迭代器

在C++中,list是一个双向链表的容器,它提供了方便的插入、删除和访问元素的方法。其中,list迭代器是一个封装了指向链表节点的指针的对象,并提供了方便的操作链表的方法,与原生指针不同。

为了模拟list的实现,我们需要自己实现一个双向链表,并将其封装在一个类中,提供类似list的接口。

首先,我们定义链表节点的结构体:

template
struct Node {
T data;
Node prev;
Node
next;
Node(const T& d) : data(d), prev(nullptr), next(nullptr) {}
};

该结构体表示链表的一个节点,包含元素的值、前后两个指针,我们为它定义了一个构造函数,使用给定的元素值初始化节点。

然后,我们定义链表类:

template
class List {
public:
List();
~List();
void push_front(const T& val);
void push_back(const T& val);
void pop_front();
void pop_back();
T& front();
T& back();
bool empty() const;
size_t size() const;
private:
Node head;
Node
tail;
size_t list_size;
};

该类中包含了插入、删除、访问元素的方法,类似于list的接口。其中,head和tail分别指向链表的头、尾节点,list_size表示链表的大小。

下面是该类方法的实现:

template
List::List() : head(nullptr), tail(nullptr), list_size(0) {}

template
List::~List() {
while (head != nullptr) {
Node* tmp = head->next;
delete head;
head = tmp;
}
}

template
void List::push_front(const T& val) {
Node* new_node = new Node(val);
if (head == nullptr) {
head = tail = new_node;
} else {
new_node->next = head;
head->prev = new_node;
head = new_node;
}
++list_size;
}

template
void List::push_back(const T& val) {
Node* new_node = new Node(val);
if (head == nullptr) {
head = tail = new_node;
} else {
new_node->prev = tail;
tail->next = new_node;
tail = new_node;
}
++list_size;
}

template
void List::pop_front() {
if (head == nullptr) return;
if (head == tail) {
delete head;
head = tail = nullptr;
} else {
Node* tmp = head;
head = head->next;
head->prev = nullptr;
delete tmp;
}
--list_size;
}

template
void List::pop_back() {
if (head == nullptr) return;
if (head == tail) {
delete head;
head = tail = nullptr;
} else {
Node* tmp = tail;
tail = tail->prev;
tail->next = nullptr;
delete tmp;
}
--list_size;
}

template
T& List::front() {
return head->data;
}

template
T& List::back() {
return tail->data;
}

template
bool List::empty() const {
return head == nullptr;
}

template
size_t List::size() const {
return list_size;
}

注意到上述方法中,我们使用了封装了链表节点指针的Node*类型而不是原生指针,这样可以避免使用指针访问链表节点时的内存问题,提供了更安全的访问方式。

最后,使用类List就可以像list一样操作双向链表了:

List lst;
lst.push_back(1);
lst.push_back(2);
lst.push_back(3);
lst.pop_front();
lst.pop_back();
for (auto& x : lst) {
std::cout << x << " ";
}

如上述代码所示,我们可以通过调用push_back()和push_front()方法插入元素,通过pop_front()和pop_back()方法删除元素,通过front()和back()方法访问头尾元素,以及通过empty()和size()方法查看链表是否为空和大小等信息。

相关文章
|
5天前
|
存储 Java
Java学习笔记 List集合的定义、集合的遍历、迭代器的使用
Java学习笔记 List集合的定义、集合的遍历、迭代器的使用
|
6天前
|
编译器
【Bug记录】list模拟实现const迭代器类
【Bug记录】list模拟实现const迭代器类
|
1天前
|
安全 NoSQL Redis
C++新特性-智能指针
C++新特性-智能指针
|
5天前
|
编译器 C++
virtual类的使用方法问题之在C++中获取对象的vptr(虚拟表指针)如何解决
virtual类的使用方法问题之在C++中获取对象的vptr(虚拟表指针)如何解决
|
5天前
|
安全 编译器 容器
C++STL容器和智能指针
C++STL容器和智能指针
|
6天前
|
C语言
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
|
6天前
|
C语言
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
|
6天前
|
存储 编译器 C语言
【C初阶——指针3】鹏哥C语言系列文章,基本语法知识全面讲解——指针(3)
【C初阶——指针3】鹏哥C语言系列文章,基本语法知识全面讲解——指针(3)
|
7天前
|
C++
C++通过文件指针获取文件大小
C++通过文件指针获取文件大小
11 0
|
7天前
|
编译器 C语言 C++
【C++关键字】指针空值nullptr(C++11)
【C++关键字】指针空值nullptr(C++11)