C++模拟实现List迭代器详解

C++模拟实现List迭代器详解

前言

本文将介绍如何在 C++ 中实现 List 容器的迭代器(iterator),并通过两个示例说明其用法。迭代器可以遍历容器中的元素,并灵活地进行读写操作。这是 C++ 中常用的操作之一,对于理解 C++ 中的容器非常有帮助。

实现 List 迭代器

概述

在 C++ 中,每个容器都有其对应的迭代器,List 也不例外。List 迭代器可以通过访问器实现,其定义和实现如下:

template<typename T>
struct Node{
    T data;
    Node* pre;
    Node* nxt;

    // 构造函数和析构函数
    Node():pre(nullptr),nxt(nullptr){}
    Node(T d, Node* p, Node* n):data(d),pre(p),nxt(n){}
    ~Node(){}

    // 拷贝构造函数和拷贝赋值运算符
    Node(const Node& n):data(n.data),pre(n.pre),nxt(n.nxt){}
    Node& operator=(const Node& n)
    {
        if(this != &n)
        {
            data = n.data;
            pre = n.pre;
            nxt = n.nxt;
        }
        return *this;
    }
};

template <typename T>
class List; // 为了提前声明 List,这里只定义迭代器

template <typename T>
class ListIterator{
    friend class List<T>;
private:
    Node<T>* curr;
public:
    ListIterator(){}
    ListIterator(Node<T>* ptr):curr(ptr){}
    ListIterator(const ListIterator<T>& li):curr(li.curr){}
    ~ListIterator(){}

    bool operator==(const ListIterator<T>& li) const
    {
        return curr == li.curr;
    }

    bool operator!=(const ListIterator<T>& li) const
    {
        return curr != li.curr;
    }

    T& operator*() const
    {
        return curr->data;
    }

    ListIterator<T>& operator++()
    {
        curr = curr->nxt;
        return *this;
    }

    ListIterator<T>& operator++(int)
    {
        ListIterator<T> tmp = *this;
        curr = curr->nxt;
        return tmp;
    }

    ListIterator<T>& operator--()
    {
        curr = curr->pre;
        return *this;
    }

    ListIterator<T>& operator--(int)
    {
        ListIterator<T> tmp = *this;
        curr = curr->pre;
        return tmp;
    }

    ListIterator<T>& operator=(const ListIterator<T>& li)
    {
        if(this != &li)
        {
            curr = li.curr;
        }
        return *this;
    }
};

代码中的 ListIterator 包含了指向节点的 Node<T>* curr 指针,以及实现迭代器相关操作的成员函数。该类的构造函数、拷贝构造函数、析构函数和赋值运算符都十分简单。重载操作符包括比较运算符(==!=)、解引用运算符(*)、前后缀自增和自减运算符(++--)。需要注意的是,自增和自减运算符需要实现前后缀两种操作方法。

实现 List

下面是一个简单的 List 实现,该实现包含了常用的操作函数(插入、删除和排序)以及迭代器相关函数。

template<typename T>
class List{
public:
    typedef ListIterator<T> iterator;

    List();
    List(const List<T>& l);
    ~List();
    List<T>& operator=(const List<T>& l);

    bool empty() const;
    int size() const;
    void clear();
    void reverse();
    void swap(List<T>& l);

    T& front();
    const T& front() const;
    T& back();
    const T& back() const;

    void push_front(const T& data);
    void push_back(const T& data);
    iterator insert(iterator pos, const T& data);
    iterator erase(iterator pos);
    void sort();

    iterator begin();
    iterator end();
private:
    int len;
    Node<T>* head;
    Node<T>* tail;
};

template<typename T>
List<T>::List():len(0),head(new Node<T>),tail(new Node<T>)
{
    head->nxt = tail;
    tail->pre = head;
}

template<typename T>
List<T>::List(const List<T>& l):len(0),head(new Node<T>),tail(new Node<T>)
{
    head->nxt = tail;
    tail->pre = head;
    for(auto it=l.begin(); it!=l.end(); ++it)
        push_back(*it);
}

template<typename T>
List<T>::~List()
{
    clear();
    delete head;
    delete tail;
}

template<typename T>
List<T>& List<T>::operator=(const List<T>& l)
{
    if(this == &l)
        return *this;

    clear();
    for(auto it=l.begin(); it!=l.end(); ++it)
        push_back(*it);

    return *this;
}

template<typename T>
bool List<T>::empty() const
{
    return len == 0;
}

template<typename T>
int List<T>::size() const
{
    return len;
}

template<typename T>
void List<T>::clear()
{
    while(!empty())
        erase(begin());
}

template<typename T>
void List<T>::reverse()
{
    Node<T>* curr = head->nxt;
    while(curr != tail)
    {
        std::swap(curr->pre, curr->nxt);
        curr = curr->pre;
    }
    std::swap(head, tail);
}

template<typename T>
void List<T>::swap(List<T>& l)
{
    std::swap(len, l.len);
    std::swap(head, l.head);
    std::swap(tail, l.tail);
}

template<typename T>
T& List<T>::front()
{
    return *begin();
}

template<typename T>
const T& List<T>::front() const
{
    return *begin();
}

template<typename T>
T& List<T>::back()
{
    return *(--end());
}

template<typename T>
const T& List<T>::back() const
{
    return *(--end());
}

template<typename T>
void List<T>::push_front(const T& data)
{
    insert(begin(), data);
}

template<typename T>
void List<T>::push_back(const T& data)
{
    insert(end(), data);
}

template<typename T>
typename List<T>::iterator List<T>::insert(iterator pos, const T& data)
{
    Node<T>* p = pos.curr;
    Node<T>* q = new Node<T>(data, p->pre, p);
    p->pre->nxt = q;
    p->pre = q;
    return iterator(q);
}

template<typename T>
typename List<T>::iterator List<T>::erase(iterator pos)
{
    Node<T>* p = pos.curr;
    iterator ret = iterator(p->nxt);
    p->pre->nxt = p->nxt;
    p->nxt->pre = p->pre;
    delete p;
    return ret;
}

template<typename T>
void List<T>::sort()
{
    if(empty()) return;

    std::list<T> tmpList;
    for(auto it=begin(); it!=end(); ++it)
        tmpList.push_back(*it);

    tmpList.sort();

    clear();
    for(auto it:tmpList)
        push_back(it);
}

template<typename T>
typename List<T>::iterator List<T>::begin()
{
    return iterator(head->nxt);
}

template<typename T>
typename List<T>::iterator List<T>::end()
{
    return iterator(tail);
}

上述代码中,利用 Node<T> 类来定义节点的数据类型,同时 List 类中包含了一个头结点和一个尾节点,并实现了常用的操作函数。注意到 List 中包含了指向节点的指针,并通过构造函数、拷贝构造函数、析构函数和赋值运算符进行了初始化和清理。此外,注意到 List 中自己实现了 push_frontpush_backinserterase 等操作函数,这些操作函数都需要首先进行节点的内存分配操作。

示例说明

示例1:List的基本操作

下面是使用 List 容器的一个示例,演示了基本的遍历和修改操作:

#include <iostream>
#include "List.h"

using namespace std;

int main()
{
    List<int> l1;
    for(int i=0; i<10; ++i)
        l1.push_back(i);

    cout << "l1 = ";
    for(auto it=l1.begin(); it!=l1.end(); ++it)
        cout << *it << " ";
    cout << endl;

    List<int> l2(l1);
    cout << "l2 = ";
    for(auto it=l2.begin(); it!=l2.end(); ++it)
        cout << *it << " ";
    cout << endl;

    for(auto it=l1.begin(); it!=l1.end(); ++it)
        *it = 2*(*it);

    cout << "l1 = ";
    for(auto it=l1.begin(); it!=l1.end(); ++it)
        cout << *it << " ";
    cout << endl;

    l2.clear();
    cout << "l2 is " << (l2.empty() ? "empty" : "not empty") << endl;

    return 0;
}

代码中,使用了 List 的常用操作,包括构造函数、迭代器、遍历和修改等。其中第一行使用了 List 的默认构造函数,并依次调用 push_back 函数插入元素。输出结果如下:

l1 = 0 1 2 3 4 5 6 7 8 9
l2 = 0 1 2 3 4 5 6 7 8 9
l1 = 0 2 4 6 8 10 12 14 16 18
l2 is empty

可以看到,随着 List 中元素的插入、遍历和修改,输出的结果一直在变化,而所有的操作都是通过自定义的迭代器实现的。

示例2:List的排序操作

下面是使用 List 容器的第二个示例,演示了排序操作:

#include <iostream>
#include "List.h"

using namespace std;

int main()
{
    List<int> l;
    for(int i=0; i<10; ++i)
        l.push_back(rand()%100);

    cout << "List:";
    for(auto it=l.begin(); it!=l.end(); ++it)
        cout << " " << *it;
    cout << endl;

    l.sort();
    cout << "Sorted list:";
    for(auto it=l.begin(); it!=l.end(); ++it)
        cout << " " << *it;
    cout << endl;

    return 0;
}

代码中,通过 List::sort 函数对 List 进行排序,并输出排序结果。注意到,由于 List 是一个双向链表,所以排序操作使用了 std::list 的算法来实现。输出结果如下:

List: 45 50 14 64 73 42 93 0 61 72
Sorted list: 0 14 42 45 50 61 64 72 73 93

可以看到, List::sort 函数可以对罗列数据进行排序。其中的排序算法是基于 std::list 的算法实现的,具有较高的效率和良好的可维护性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++模拟实现List迭代器详解 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 更新完Win11系统后C盘变小了怎么办? win11一更新c盘就变小解决办法

    更新完Win11系统后C盘变小了怎么办? 当你更新完Win11系统后,发现C盘的可用空间变小了,可能是由于系统更新过程中产生了一些临时文件或者备份文件,导致C盘空间被占用。下面是解决这个问题的一些方法: 方法一:清理临时文件和备份文件 打开“设置”菜单,点击“系统”选项。 在左侧导航栏中选择“存储”。 在“存储”页面中,点击“临时文件”。 在“临时文件”页面…

    other 2023年8月2日
    00
  • Win11怎么查看文件关联?Win11显示文件扩展名关联方法

    Win11怎么查看文件关联? 在Windows 11中,你可以通过以下步骤查看文件关联: 打开“设置”:点击任务栏上的“开始”按钮,然后点击“设置”图标(齿轮状图标)。 进入“应用”设置:在设置窗口中,点击左侧导航栏中的“应用”选项。 打开“默认应用”页面:在“应用”设置页面中,点击左侧导航栏中的“默认应用”选项。 查看文件关联:在“默认应用”页面中,向下滚…

    other 2023年8月5日
    00
  • 如何使用“purge 命令”清理 Mac OS X 内存空间

    如何使用 purge 命令清理 Mac OS X 内存空间 在 Mac OS X 上,purge 命令可以用于清理内存空间,以提高系统的性能和响应速度。purge 命令会强制系统将内存中的缓存数据写入磁盘,并释放已使用的内存。下面是使用 purge 命令清理 Mac OS X 内存空间的完整攻略。 步骤 1:打开终端 首先,打开终端应用程序。您可以在“应用程…

    other 2023年7月31日
    00
  • 如何快速升级苹果iOS10开发者预览版Beta1?iOS10开发者预览版描述文件安装

    如何快速升级苹果iOS10开发者预览版Beta1? 苹果iOS 10是苹果公司的最新移动操作系统,目前还处于开发者预览版,开发者需要通过特殊的流程升级安装。本文将详细介绍如何快速升级苹果iOS 10开发者预览版Beta1。 步骤一:注册并登录苹果开发者账号 首先,你需要拥有一个苹果开发者账号。如果还没有账号,可以前往苹果开发者网站注册并购买。 步骤二:下载i…

    other 2023年6月26日
    00
  • C++中的变长参数深入理解

    C++中的变长参数深入理解 一、什么是变长参数 变长参数,即“可变参数”,指的是函数参数的数量和类型在编译阶段并不确定,而是在运行时动态决定。在C++中,我们可以使用标准库头文件<cstdarg>中的宏来实现变长参数。 二、如何实现变长参数 实现变长参数的核心宏有三个,分别是va_list、va_start和va_arg。 1. va_list宏…

    other 2023年6月27日
    00
  • ios基础-瀑布流

    iOS基础-瀑布流 什么是瀑布流? 瀑布流是一种常见的UI设计,常常用于网页和移动应用程序中的图片展示。瀑布流布局以其独特的分布方式、流体布局的特点以及其吸引人的外观而获得了很多粉丝。 这个布局的名称瀑布流,源于其布局方式,像是由多个不同大小的石块按照规定的方式堆砌而成的瀑布,每一块石头都各有不同的形状、大小和位置,整个瀑布流的视觉效果非常美观。 瀑布流设计…

    其他 2023年3月29日
    00
  • WinXP内存优化教程(可提供系统运行速度)

    WinXP内存优化教程 在这个教程中,我将向您介绍一些优化Windows XP系统内存的方法,以提高系统的运行速度。以下是详细的步骤: 步骤一:禁用不必要的启动项 打开任务管理器:按下Ctrl + Shift + Esc键,或者右键点击任务栏并选择“任务管理器”。 切换到“启动”选项卡。 禁用不必要的启动项:右键点击不需要的启动项,并选择“禁用”。 示例说明…

    other 2023年8月2日
    00
  • jwt加密解密

    JWT加密解密攻略 JSON Web Token(JWT)是一种用于身份验证的开放标准,可以在网络应用间传递声明。JWT通常由三部分组成:头部、载荷和签名。本文将介如何使用Python进行JWT的加密和解密,并提供两个示例说明。 安装PyJWT模块 在开始之前,需要先安PyJWT模块。可以使用pip命令进行安装: pip install PyJWT JWT加…

    other 2023年5月7日
    00
合作推广
合作推广
分享本页
返回顶部