list模拟实现

目录

节点结构

构造函数

insert

erase

push_back

push_front

pop_front

pop_back

拷贝构造

析构函数

赋值重载

正向迭代器实现

clear

反向迭代器实现

测试list

附完整代码


参照数据结构篇: 带头双向循环链表

节点结构

cpp 复制代码
namespace dck
{
    template <class T>
    struct list_node
    {
        T _data;
        list_node<T> *_next;
        list_nodce<T> *_prev;

        list_node(const T &x = T())
            : _data(x), _next(nullptr), _prev(nullptr)
        {}
    };

    template <class T>
    class list
    {
        typedef list_node<T> Node;
    private:
        Node *_head;  // 带哨兵位的头节点指针
        size_t _size; // 链表的节点个数
    };
}

构造函数

cpp 复制代码
void empty_init()
{
    _head = new Node;
    _head->_next = _head;
    _head->_prev = _head;
    _size = 0;
}

// 构造函数
list()
{
    empty_init();
}

insert

cpp 复制代码
iterator insert(iterator pos, const T &val)
{
    Node *cur = pos._node; // 获取原生指针
    Node *newnode = new Node(val);
    Node *prev = cur->_prev;

    prev->_next = newnode;
    newnode->_prev = prev;

    newnode->_next = cur;
    cur->_prev = newnode;

    ++_size;
    return iterator(newnode);
}

erase

cpp 复制代码
iterator erase(iterator pos)
{
    Node *cur = pos._node;
    Node *prev = cur->_prev;
    Node *next = cur->_next;

    delete cur;
    prev->_next = next;
    next->_prev = prev;
    _size--;
    return iterator(next);
}

push_back

cpp 复制代码
void push_back(const T &x)
{
    insert(end(), x);
}

push_front

cpp 复制代码
void push_front(const T &x)
{
    insert(begin(), x);
}

pop_front

cpp 复制代码
void pop_front()
{
    erase(begin());
}

pop_back

cpp 复制代码
void pop_back()
{
    erase(--end());
}

拷贝构造

cpp 复制代码
list(const list<T> &lt)
{
    empty_init();
    for (auto e : lt)
    {
        push_back(e);
    }
}

析构函数

cpp 复制代码
~list()
{
    clear();
    delete _head;
    _head = nullptr;
}​

赋值重载

cpp 复制代码
void swap(list<T> &lt)
{
    std::swap(_head, lt._head);
    std::swap(_size, lt._size);
}
list<T> &operator=(list<T> lt)
{
    swap(lt);
    return *this;
}

正向迭代器实现

● 之前学习的迭代器本质是原生指针,但list的迭代器是对节点指针封装的类,因为迭代器提供的统一操作是++/--来访问前一个或者后一个节点,但是list是链表,因此我们要将++/--实现成类的运算符重载函数,就可以让++/--实现访问前一个/后一个节点的效果

● 由于正向普通迭代器和正向const迭代器的类型不同,是需要实现两个类的,但我们可以给类添加额外两个模版参数,就可以控制是普通迭代器还是const迭代器

cpp 复制代码
template <class T, class Ref, class Ptr> // 第二个参数是引用,第三个参数是指针
struct __list_iterator                   // 前加_一般表示内部的实现
{
    typedef list_node<T> Node;
    typedef __list_iterator<T, Ref, Ptr> self;
    Node *_node;

    __list_iterator(Node *node)
        : _node(node)
    {
    }

    self &operator++()
    {
        _node = _node->_next;
        return *this;
    }

    self operator++(int)
    {
        self tmp(*this);
        _node = _node->_next;
        return tmp;
    }

    self &operator--()
    {
        _node = _node->_prev;
        return *this;
    }

    self operator--(int)
    {
        self tmp(*this);
        _node = _node->_prev;
        return tmp;
    }

    Ref operator*()
    {
        return _node->_data;
    }

    bool operator!=(const self &s)
    {
        return _node != s._node;
    }

    bool operator==(const self &s)
    {
        return _node == s._node;
    }

    Ptr operator->()
    {
        return &_node->_data;
    }
};
cpp 复制代码
iterator begin()
{
    return _head->_next;
}

const_iterator begin() const
{
    return _head->_next;
}

iterator end()
{
    return _head;
}

const_iterator end() const
{
    return _head;
}

clear

cpp 复制代码
void clear()
{
    iterator it = begin();
    while (it != end())
    {
        it = erase(it);
    }
}

反向迭代器实现

● 反向迭代器可以用正向迭代器去适配,反向迭代器的++/--本质就是正向迭代器的--/++

● 迭代器判断相等和不相等本质是在比较底层的节点指针是否相等

reverse_iterator.h 文件

cpp 复制代码
template<class Iterator, class Ref, class Ptr>
class ReverseIterator
{
public:
	typedef ReverseIterator<Iterator, Ref, Ptr> Self;

	ReverseIterator(Iterator it)
		:_it(it)
	{}

	//前置++
	Self& operator++()
	{
		--_it;
		return *this;
	}

	//后置++
	Self operator++(int)
	{
		Self tmp(*this);
		--_it;
		return tmp;
	}

	Ref operator*()
	{
		//自己实现
		//return *_it;
	}

	Ptr operator->()
	{
		//自己实现
		return _it.operator->();
	}

	bool operator!=(const Self& s)
	{
		return _it != s._it;
	}

private:
	Iterator _it;
};

list.h 文件

cpp 复制代码
template <class T>
class list
{
    typedef list_node<T> Node;

public:
    typedef __list_iterator<T, T &, T *> iterator;                                        // 非const迭代器
    typedef __list_iterator<T, const T &, const T *> const_iterator;                      // const迭代器
    typedef ReverseIterator<iterator, T &, T *> reverse_iterator;                         // 非const反向迭代器
    typedef ReverseIterator<const_iterator, const T &, const T *> const_reverse_iterator; // const反向迭代器

    reverse_iterator rbegin()
    {
        return iterator(--end()); // 自己实现的
    }

    reverse_iterator rend()
    {
        return iterator(end()); // 自己实现的
    }

    const_reverse_iterator rbegin() const
    {
        return const_iterator(--end()); // 自己实现的
    }

    const_reverse_iterator rend() const
    {
        return const_iterator(end()); // 自己实现的
    }
}

而库中的实现和我们不太一样,不一样的地方在于库中反向迭代器的rbegin与rend位置和我们自己写的不一样,下图rbegin和rend的位置是库中的实现,是呈现对称结构的,而库中迭代器解引用访问的是前一个数据,也就是先让原生指针--, 然后解引用访问数据!

reverse_iterator.h 文件

cpp 复制代码
template<class Iterator, class Ref, class Ptr>
class ReverseIterator
{
public:
	typedef ReverseIterator<Iterator, Ref, Ptr> Self;

	ReverseIterator(Iterator it)
		:_it(it)
	{}

	//前置++
	Self& operator++()
	{
		--_it;
		return *this;
	}

	//后置++
	Self operator++(int)
	{
		Self tmp(*this);
		--_it;
		return tmp;
	}

	Ref operator*()
	{
		//库中的
		Iterator cur = _it;
		return *(--cur);
	}

	Ptr operator->()
	{
		//库中的
		return &(operator*());
	}

	bool operator!=(const Self& s)
	{
		return _it != s._it;
	}

private:
	Iterator _it;
};

list.h 文件

cpp 复制代码
template <class T>
class list
{
public:
    typedef __list_iterator<T, T &, T *> iterator;                                        // 非const迭代器
    typedef __list_iterator<T, const T &, const T *> const_iterator;                      // const迭代器
    typedef ReverseIterator<iterator, T &, T *> reverse_iterator;                         // 非const反向迭代器
    typedef ReverseIterator<const_iterator, const T &, const T *> const_reverse_iterator; // const反向迭代器

    reverse_iterator rbegin()
    {
        return iterator(end()); // 库中的
    }

    reverse_iterator rend()
    {
        return iterator(begin()); // 库中的
    }

    const_reverse_iterator rbegin() const
    {
        return const_iterator(end()); // 库中的
    }

    const_reverse_iterator rend() const
    {
        return const_iterator(begin()); // 库中的
    }
};

测试list

cpp 复制代码
#include <iostream>
#include "list.h"
using namespace std;

void print(const dck::list<int> &lt)
{
	dck::list<int>::const_iterator it = lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

void printReverse(const dck::list<int> &lt)
{
	dck::list<int>::const_reverse_iterator it = lt.rbegin();
	while (it != lt.rend())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

void test1()
{
	dck::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_front(3);
	lt.push_front(4);
	print(lt);
	lt.pop_back();
	lt.pop_front();
	print(lt);
}

void test2()
{
	dck::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.insert(++lt.begin(), 10);
	print(lt);
	lt.erase(++lt.begin());
	print(lt);
}

void test3()
{
	dck::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	printReverse(lt);
}

void test4()
{
	dck::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	dck::list<int> lt1(lt); 
	print(lt);

	dck::list<int> lt2;
	lt2.push_back(10);
	lt2.push_back(20);
	lt2.push_back(30);
	lt2.push_back(40);
	lt2 = lt; 
	print(lt2);
}

int main()
{
	test1();
	test2();
	test3();
	test4();
	return 0;
}

附完整代码

reverse_iterator.h

cpp 复制代码
//用正向迭代器适配方向迭代器
template<class Iterator, class Ref, class Ptr>
class ReverseIterator
{
public:
	typedef ReverseIterator<Iterator, Ref, Ptr> Self;

	ReverseIterator(Iterator it)
		:_it(it)
	{}

	//前置++
	Self& operator++()
	{
		--_it;
		return *this;
	}

	//后置++
	Self operator++(int)
	{
		Self tmp(*this);
		--_it;
		return tmp;
	}

	Ref operator*()
	{
		//库中的
		Iterator cur = _it;
		return *(--cur);
	}

	Ptr operator->()
	{
		//库中的
		return &(operator*());
	}

	bool operator!=(const Self& s)
	{
		return _it != s._it;
	}

private:
	Iterator _it;
};

list.h

cpp 复制代码
#include <iostream>
using namespace std;
#include "reverse_iterator.h"

namespace dck
{
    template <class T>
    struct list_node
    {
        T _data;
        list_node<T> *_next;
        list_node<T> *_prev;

        list_node(const T &x = T())
            : _data(x), _next(nullptr), _prev(nullptr)
        {}
    };

    template <class T, class Ref, class Ptr> // 第二个参数是引用,第三个参数是指针
    struct __list_iterator                   // 前加_一般表示内部的实现
    {
        typedef list_node<T> Node;
        typedef __list_iterator<T, Ref, Ptr> self;
        Node *_node;

        __list_iterator(Node *node)
            : _node(node)
        {
        }

        self &operator++()
        {
            _node = _node->_next;
            return *this;
        }

        self operator++(int)
        {
            self tmp(*this);
            _node = _node->_next;
            return tmp;
        }

        self &operator--()
        {
            _node = _node->_prev;
            return *this;
        }

        self operator--(int)
        {
            self tmp(*this);
            _node = _node->_prev;
            return tmp;
        }

        Ref operator*()
        {
            return _node->_data;
        }

        bool operator!=(const self &s)
        {
            return _node != s._node;
        }

        bool operator==(const self &s)
        {
            return _node == s._node;
        }

        Ptr operator->()
        {
            return &_node->_data;
        }
    };

    // list的实现
    template <class T>
    class list
    {
        typedef list_node<T> Node;
    public:
        typedef __list_iterator<T, T &, T *> iterator;                   // 非const迭代器
        typedef __list_iterator<T, const T &, const T *> const_iterator; // const迭代器
        typedef ReverseIterator<iterator, T &, T *> reverse_iterator;                         // 非const反向迭代器
        typedef ReverseIterator<const_iterator, const T &, const T *> const_reverse_iterator; // const反向迭代器

        reverse_iterator rbegin()
        {
            return iterator(end()); // 库中的
        }

        reverse_iterator rend()
        {
            return iterator(begin()); // 库中的
        }

        const_reverse_iterator rbegin() const
        {
            return const_iterator(end()); // 库中的
        }

        const_reverse_iterator rend() const
        {
            return const_iterator(begin()); // 库中的
        }

        iterator begin()
        {
            return _head->_next;
        }

        const_iterator begin() const
        {
            return _head->_next;
        }

        iterator end()
        {
            return _head;
        }

        const_iterator end() const
        {
            return _head;
        }

        void empty_init()
        {
            _head = new Node;
            _head->_next = _head;
            _head->_prev = _head;
            _size = 0;
        }

        // 构造函数
        list()
        {
            empty_init();
        }

        // 清空数据
        void clear()
        {
            iterator it = begin();
            while (it != end())
            {
                it = erase(it);
            }
        }

        // 拷贝构造 --- 一个节点一个节点尾插即可
        list(const list<T> &lt)
        {
            empty_init();
            for (auto e : lt)
            {
                push_back(e);
            }
        }

        void swap(list<T> &lt)
        {
            std::swap(_head, lt._head);
            std::swap(_size, lt._size);
        }
        //赋值重载
        list<T> &operator=(list<T> lt)
        {
            swap(lt);
            return *this;
        }

        // 析构函数
        ~list()
        {
            clear();
            delete _head;
            _head = nullptr;
        }

        void push_back(const T &x)
        {
            insert(end(), x);
        }

        void push_front(const T &x)
        {
            insert(begin(), x);
        }

        void pop_front()
        {
            erase(begin());
        }

        void pop_back()
        {
            erase(--end());
        }

        // 在pos之前插入节点
        iterator insert(iterator pos, const T &val)
        {
            Node *cur = pos._node; // 获取原生指针
            Node *newnode = new Node(val);
            Node *prev = cur->_prev;

            prev->_next = newnode;
            newnode->_prev = prev;

            newnode->_next = cur;
            cur->_prev = newnode;

            ++_size;
            return iterator(newnode);
        }

        // 删除pos位置的节点, 返回下一个位置的迭代器
        iterator erase(iterator pos)
        {
            Node *cur = pos._node;
            Node *prev = cur->_prev;
            Node *next = cur->_next;

            delete cur;
            prev->_next = next;
            next->_prev = prev;
            _size--;
            return iterator(next);
        }

        size_t size()
        {
            return _size;
        }

    private:
        Node *_head;  // 带哨兵位的头节点指针
        size_t _size; // 链表的节点个数
    };
}
相关推荐
懒羊羊大王&15 小时前
模版进阶(沉淀中)
c++
owde16 小时前
顺序容器 -list双向链表
数据结构·c++·链表·list
GalaxyPokemon16 小时前
Muduo网络库实现 [九] - EventLoopThread模块
linux·服务器·c++
W_chuanqi16 小时前
安装 Microsoft Visual C++ Build Tools
开发语言·c++·microsoft
tadus_zeng17 小时前
Windows C++ 排查死锁
c++·windows
EverestVIP17 小时前
VS中动态库(外部库)导出与使用
开发语言·c++·windows
胡斌附体17 小时前
qt socket编程正确重启tcpServer的姿势
开发语言·c++·qt·socket编程
GalaxyPokemon18 小时前
Muduo网络库实现 [十] - EventLoopThreadPool模块
linux·服务器·网络·c++
守正出琦18 小时前
日期类的实现
数据结构·c++·算法
ChoSeitaku18 小时前
NO.63十六届蓝桥杯备战|基础算法-⼆分答案|木材加工|砍树|跳石头(C++)
c++·算法·蓝桥杯