本文给出C++ STL中list的主要函数模拟实现
在给出代码之前 , 我想作以下几点说明 :
1 . 本代码只是模拟list的实现 , 由于我本人才疏学浅 , 代码实现可能与STL版本大相径庭
2 . STL中的迭代器是用模板类实现 , 本代码只是用一个类指针来模拟 , 因此使用较为繁琐
3 . 本代码的函数版本较为简易 , 几乎不支持任何泛型算法
//头文件 mylist.h
#pragma once
#include<iostream>
using namespace std;
template <typename t> class Node
{
public:
t data;
Node* next;
Node* prev ;
};
template <typename T> class mylist:public Node<T>
{
public:
void construct(); //构造list
mylist(); //空list
mylist(int size_of_list); //指定大小的list
mylist(initializer_list<T>ls); //初始化列表
mylist(int size_of_list, T val); //指定大小的list和所有初始元素
mylist(mylist& A); //拷贝构造函数
void push_back(T val); //尾插
void push_front(T val); //头插
void pop_back(); //尾弹
void pop_front(); //首弹
bool empty(); //判断list是否为空
void resize(int n); //调用resize(n)将list的长度改为只容纳n个元素,超出的元素将被删除。如果n比list原来的长度长,那么默认超出的部分元素置为0。
void clear(); //清空所有元素
void remove(T data); //删除具有特定值的元素
void reverse(); //反转list(迭代法)
void assign(int n, T val); //将list中的n个元素替换为val
mylist<T>& assign(Node<T> *A, Node<T> *B);//将一定范围内的元素替换到list
void merge(mylist<T> &A); //将另一个list合并于本list中
Node<T>* erase(Node<T>* it); //删除某个元素
Node<T>* erase(Node<T>* lhs, Node<T>* rhs); //删除某个范围内的元素
Node<T>* insert(Node<T>* it, T val); //在某个位置插入一个元素
Node<T>* insert(Node<T>* it, int n, T val); //某个位置插入n个元素
T operator[](int n); //重载[] 用于便捷访问list中的元素
T operator*(); //重载* 用于解引用list的迭代器
mylist<T> &operator++(); //前置递增
mylist<T> &operator++(int); //后置递增
mylist<T> &operator--(); //前置递减
mylist<T> &operator--(int); //后置递减
mylist<T> &operator+=(int step); //复合赋值运算符
mylist<T> &operator-=(int step); //复合赋值运算符
void operator=(Node<T>* it); //重载= 用来简化迭代器
Node<T>* iterator; //模拟迭代器
Node<T>* begin(); //首迭代器,list第一个元素的位置
Node<T>* end(); //尾迭代器,list最后一个元素之后一个位置
Node<T>* rbegin(); //反向首迭代器
Node<T>* rend(); //反向尾迭代器
int size(); //获取list大小的接口
T& back(); //返回第一个元素的值
T& front(); //返回最后一个元素的值
void display(); //用箭头显示该链表所有元素
private:
int renew_len(); //获取当前list的大小
int len; //list的大小
Node<T>* head; //list的头结点(头结点数据域为空)
Node<T>* tail; //list的尾结点(尾结点是list的最后一个结点)
};
template <class T>void mylist<T>::construct()
{
head = new Node<T>;
head->prev = nullptr;
head->next = nullptr;
iterator = head;
len = 0;
}
template <class T>mylist<T>::mylist()
{
this->construct();
}
template <class T>mylist<T>::mylist(int size_of_list)
{
this->construct();
for (int i = 0; i < size_of_list; ++i)
{
this->push_back(0);
}
}
template<class T>mylist<T>::mylist(initializer_list<T>ls)
{
this->construct();
for (auto& x : ls)
{
this->push_back(x);
}
}
template<class T>mylist<T>::mylist(int size_of_list, T val)
{
this->construct();
for (int i = 0; i < size_of_list; ++i)
{
this->push_back(val);
}
}
template<class T>mylist<T>::mylist(mylist& A)
{
this->construct();
this->assign(A.begin(), A.tail);
}
template <class T> void mylist<T>::push_back(T val)
{
if (head->next == nullptr)
{
tail = head;
}
Node<T>* tmp = new Node<T>;
tmp->data = val;
tmp->prev = tail;
tail->next = tmp;
tail = tmp;
tail->next = nullptr;
++len;
}
template <class T> void mylist<T>::push_front(T val)
{
if (head->next == nullptr)
{
this->push_back(val);
}
else
{
Node<T>* tmp = new Node<T>;
tmp->data = val;
tmp->next = head->next;
tmp->prev = head->next->prev;
head->next->prev = tmp;
head->next = tmp;
}
++len;
}
template <class T> bool mylist<T>::empty()
{
return size() ? true : false;
}
template <class T>void mylist<T>::resize(int n)
{
Node<T>* p = head;
int size = len;
if (n == size)
{
return;
}
else if (n < size)
{
for (int i = 0; i < n; ++i)
{
p = p->next;
}
p = p->next;
Node<T>* tmp = p;
bool flag = true;
while (flag)
{
if (p == tail)
{
flag = false;
}
p = erase(p);
}
}
else if (n > size)
{
for (int i = 0; i < n - size; ++i)
{
push_back(0);
}
}
renew_len();
}
template <class T> void mylist<T>::clear()
{
Node<T>* p = head;
Node<T>* tmp;
for (int i = 0; i < len; ++i)
{
tmp = p->next;
delete p;
p = tmp;
}
head->next = nullptr;
renew_len();
}
template <class T> Node<T>* mylist<T>::erase(Node<T>* it)
{
if (it ->next==nullptr)
{
tail = tail->prev;
it->prev->next = nullptr;
delete it;
renew_len();
return tail->next;
}
else
{
Node<T>* tmp = it->next;
it->prev->next = it->next;
it->next->prev = it->prev;
delete it;
renew_len();
return tmp;
}
}
template <class T> Node<T>* mylist<T>::erase(Node<T>* lhs, Node<T>* rhs)
{
Node<T>* p = lhs;
bool flag = true;
while (flag)
{
if (p == rhs)
{
flag = false;
}
else
{
p = erase(p);
}
}
if (rhs->next==nullptr)
{
tail = lhs->prev;
}
renew_len();
return p;
}
template <class T> int mylist<T>::renew_len()
{
int j = 0;
if (head->next == nullptr)
{
this->len = j;
return j;
}
Node<T>* tmp = head;
while (tmp ->next!=nullptr)
{
tmp = tmp->next;
++j;
}
this->len = j;
return j;
}
template <class T> int mylist<T>::size()
{
try
{
if (len < 0)
{
throw runtime_error("The size of list cannot less than 0");
}
return len;
}
catch (runtime_error& err)
{
cout << err.what();
}
}
template <class T>T& mylist<T>::back()
{
return tail->data;
}
template<class T>T& mylist<T>::front()
{
return head->next->data;
}
template<class T> Node<T>* mylist<T>::begin()
{
return head->next;
}
template<class T>Node<T>* mylist<T>::end()
{
return tail->next;
}
template<class T> Node<T>* mylist<T>::rend()
{
return head;
}
template<class T>Node<T>* mylist<T>::rbegin()
{
return tail;
}
template<class T>T mylist<T>::operator[](int n)
{
try
{
if (len == 0)
{
throw(runtime_error("error:The list is empty! "));
}
}
catch (runtime_error& err)
{
cout << err.what();
}
Node<T>* p = head->next;
for (int i = 0; i < n; ++i)
{
p = p->next;
}
return p->data;
}
template<class T>T mylist<T>::operator*()
{
try
{
if (head->next == nullptr)
{
throw runtime_error("The list is empty!");
}
else
{
return iterator->data;
}
}
catch (runtime_error& err)
{
cout << err.what() << endl;
}
}
template<class T>mylist<T>& mylist<T>::operator++()
{
this->iterator = this->iterator->next;
return *this;
}
template<class T>mylist<T>&mylist<T>::operator--()
{
if (iterator == end())
{
iterator = tail;
return *this;
}
iterator = iterator->prev;
return *this;
}
template<class T>mylist<T>& mylist<T>::operator++(int)
{
mylist<T>tmp = *this;
iterator = iterator->next;
return tmp;
}
template<class T>mylist<T> &mylist<T>::operator--(int)
{
if (iterator == end())
{
iterator = tail;
return *this;
}
mylist<T>tmp = *this;
iterator = iterator->prev;
return tmp;
}
template<class T>mylist<T> &mylist<T>::operator+=(int step)
{
for (int i = 0; i < step; ++i)
{
++* this;
}
return *this;
}
template<class T>mylist<T> &mylist<T>::operator-=(int step)
{
for (int i = 0; i < step; ++i)
{
--* this;
}
return *this;
}
template<class T>void mylist<T>::operator=(Node<T>* it)
{
this->iterator = it;
}
template<class T>void mylist<T>::remove(T data)
{
if (len == 0)
{
cout << "The list is empty" << endl;
return;
}
Node<T>* p = head;
while (1)
{
p = p->next;
if (p != tail)
{
if (p->data == data)
{
p = erase(p);
--* this;
}
}
if (p == tail)
{
break;
}
}
}
template<class T>void mylist<T>::display()
{
if (len == 0)
{
cout << "The list is empty" << endl;
return;
}
Node<T>* p = head;
while (1)
{
p = p->next;
cout << p->data;
if (p ->next!= nullptr)
{
cout << "-->";
}
if (p ->next == nullptr)
{
break;
}
}
cout << endl;
}
template<class T>Node<T>* mylist<T>::insert(Node<T>* it, T val)
{
Node<T>* tmp = new Node<T>;
tmp->data = val;
it->prev->next = tmp;
tmp->next = it;
tmp->prev = it->prev;
it->prev = tmp;
renew_len();
return tmp;
}
template<class T>Node<T>* mylist<T>::insert(Node<T>* it, int n, T val)
{
Node<T>* tmp = it;
for (int i = 0; i < n; ++i)
{
tmp = insert(tmp, val);
}
renew_len();
return tmp;
}
template <class T>void mylist<T>::reverse()
{
Node<T>* p = head->next;
Node<T>* newtail = head->next;
while (p != nullptr)
{
Node<T>* p_next = p->next;
p->next = p->prev;
p->prev = p_next;
p = p_next;
}
head->next = tail;
tail->prev = head;
tail = newtail;
tail->next = nullptr;
}
template <class T>void mylist<T>::pop_back()
{
this->erase(tail);
}
template <class T>void mylist<T>::pop_front()
{
this->erase(head->next);
}
template <class T>void mylist<T>::assign(int n, T val)
{
this->resize(n);
Node<T>* p = head;
while (1)
{
p = p->next;
p->data = val;
if (p == tail)
{
break;
}
}
}
template <class T>mylist<T>& mylist<T>::assign(Node<T>* A, Node<T> *B)
{
bool flag = true;
Node<T>* p1 = head;
Node<T>* p2 = A;
int cnt = 0;
while (flag)
{
if (p2 == B)
{
flag = false;
}
p2 = p2->next;
cnt++;
}
int safe_len;
if (cnt >= len)
{
safe_len = cnt;
}
else
{
safe_len = len;
}
this->resize(safe_len);
flag = true;
p2 = A;
while (flag)
{
if (p2 == B)
{
flag = false;
}
p1 = p1->next;
p1->data = p2->data;
p2 = p2->next;
}
return *this;
}
template <class T>void mylist<T>::merge(mylist &A)
{
tail->next = A.head->next;
tail = A.tail;
A.head->next = nullptr;
A.renew_len();
renew_len();
}
下面我们来对代码进行测试 :
//测试代码
#include"mylist.h"
#include<string>
int main()
{
mylist<int>L1;
mylist<char>L2{ 'A','B','C'};
mylist<string>L3{ "you","and","me" };
mylist<double>L4(5, 3.14);
L2.display();
L3.display();
L4.display();
for (int i = 1; i <= 10; i++)
{
L1.push_back(i);
}
mylist<int>L5(L1); //以L1来构造L5
for (L1.iterator = L1.begin(); L1.iterator != L1.end(); ++L1)
{
cout << *L1 << " "; //遍历并输出L1中的所有元素
}
for (int i = 1; i <= 10; i++)
{
L1.push_front(i); //头插法向L1插入元素
}
cout << endl;
L1.display();
L1.remove(9); //删除L1中值为9的元素
L1.push_back(100); //尾插100
L1.pop_front(); //首弹
L1.display();
cout << L1.size() << endl; //输出L1的大小
L1.iterator = L1.begin(); //建立L1的模拟迭代器
L1 += 5;
L1.erase(L1.iterator);
L1.display();
L1.iterator = L1.end();
L1 -= 2;
auto it2 = L1.iterator;
L1.iterator = L1.begin();
L1 += 10;
auto it1 = L1.iterator;
L1.erase(it1, it2); //it1指向L1的第11个元素,it2指向L1的倒数第二个元素
L1.display();
mylist<int>L6{ 1,2,3 };
L1.iterator = L1.begin();
it1 = L1.iterator;
L1 += 5;
it2 = L1.iterator;
cout << endl;
L6.assign(it1, it2); //it1指向L1的第1个元素,it2指向L1的第6个元素,把L1的第1个元素到第6个元素分配给L6
cout << endl;
L6.display();
L1.display();
L1.reverse(); //反转L1
L1.display();
L1.merge(L5); //将L1和L5合并于L1
L1.display();
cout << L1.back()<< endl; //输出L1的最后一个元素
L1.clear(); //清空L1
cout << L1.empty(); //判断L1是否为空
cout << endl << endl;
cout << L2[1] << endl; //输出L2的第2个元素
L2.push_front('E'); //L2首插E
L2.display();
cout << endl;
L3.push_back("love"); //L3尾插love
L3.remove("and"); //L3去除and
L3.display();
cout << endl;
L4.resize(2); //将L4大小设置为2
L4.display();
L4.resize(5); //将L4大小设置为5
L4.display();
L4.pop_back(); //尾弹L4
L4.display();
L4.pop_front(); //首弹L4
L4.display();
L4.insert(L4.begin(), 999); //在L4首部插入999
L4.iterator = L4.begin();
L4 += 3;
L4.insert(L4.iterator, 3, 777); //在L4的第4个元素位置插入3个777
L4.display();
cout << L4.size() << endl; //输出L4大小
L4.assign(7, 333); //将7个333分配给L4
L4.display();
}
最终呈现效果如下 :
代码水平不高 , 恳请大家批评指正 !