这里写目录标题
一、Lsit模拟实现
#pragma once
#include<iostream>
using namespace std;
namespace bit
{
template<class T>
struct ListNode
{
ListNode(const T& x = T())
:next(nullptr)
, prev(nullptr)
, data(x)
{}
ListNode<T>* next;
ListNode<T>* prev;
T data;
};
template<class T>
struct ListIterotor
{
typedef ListNode<T> Node;
ListIterotor(Node* n)
:node(n)
{}
/// 实现重载////////////////////////////////////////////////////////////////
///1.迭代器移动(++、--)
ListIterotor& operator++()
{
node = node->next;
return *this;
}
ListIterotor operator++(int)
{
ListIterotor temp(*this);
node = node->next;
return temp;
}
ListIterotor& operator--()
{
node = node->prev;
return *this;
}
ListIterotor operator--(int)
{
ListIterotor temp(*this);
node = node->prev;
return temp;
}
/// 2.能够解引用//////////////////////////////////////////////////////////////
T& operator*()
{
return node->data;
}
T* operator->()
{
return &(node->data);
}
/// 3.比较//////////////////////////////////////////////////////////////
bool operator!=(const ListIterotor& L)
{
return node != L.node;
}
bool operator==(const ListIterotor& L)
{
return node == L.node;
}
Node* node;
};
template<class T>
class list
{
typedef ListNode<T> Node;
public:
typedef ListIterotor<T> iterator;
private:
void MakeHead()
{
head = new Node;
head->next = head;
head->prev = head;
}
public:
//构造
list()
{
MakeHead();
}
list(int n, const T& data)
{
MakeHead();
for (int i = 0;i < n;i++)
{
push_back(data);
}
}
template<class Iterator>
list(Iterator first, Iterator last)
{
MakeHead();
while (first != last)
{
push_back(*first);
first++;
}
}
list(const list<T>& L)
{
MakeHead();
auto it = L.begin();
while (it != L.end())
{
push_back(*it);
begin++;
}
}
~list()
{
clear();
delete head;
head = nullptr;
}
//////////////////////////////////////////////////////////////
iterator begin()
{
return iterator(head->next);
}
iterator end()
{
return iterator(head);
}
//////////////////////////////////////////////////////////////////
size_t size()
{
int count = 0;
Node* temp = head->next;
while (temp != head)
{
count++;
temp = temp->next;
}
return count;
}
bool empty()const
{
return head->next == head;
}
void resize(size_t newsize, const T& data = T())
{
size_t oldsize = size();
if (oldsize < newsize)
{
//增多
while (oldsize != newsize)
{
push_back(data);
++oldsize;
}
}
else
{
//减少
while (oldsize != newsize)
{
pop_back();
++newsize;
}
}
}
/// 元素访问//////////////////////////////////////////////////////////////
T& front()
{
return head->next->data;
}
const T& front()const
{
return head->next->data;
}
T& back()
{
return head->prev->data;
}
const T& back()const
{
return head->prev->data;
}
/// 元素修改//////////////////////////////////////////////////////////////
void push_back(const T& data)
{
insert(end(),data);
}
void pop_back()
{
auto it = head->prev;
erase(it);
}
void push_front(const T& data)
{
insert(begin(), data);
}
void pop_front()
{
erase(begin());
}
iterator insert(iterator pos, const T& data)
{
Node* newnode = new Node(data);
Node* cur = pos.node;
newnode->prev = cur->prev;
newnode->next = cur;
newnode->prev->next = newnode;
cur->prev = newnode;
return iterator(newnode);
}
iterator erase(iterator pos)
{
if (pos == end())
{
return pos;
}
Node* cur = pos.node;
Node* temp = cur->next;
cur->prev->next = cur->next;
cur->next->prev = cur->prev;
delete cur;
return iterator(temp);
}
void swap(list<T>& L)
{
std::swap(head, L.head);
}
void clear()
{
Node* cur = head->next;
while (head->next != head)
{
head->next = cur->next;
delete cur;
cur = head->next;
}
head->prev = head;
}
private:
Node* head;
};
}
void Test()
{
bit::list<int> L1;
bit::list<int> L2{ 10,5 };
int arr[] = { 1,2,3,4,5 };
bit::list<int> L3(arr, arr + 3);
auto it = L3.begin();
while (it!=L3.end())
{
cout << *it << " ";
++it;
}
it = L3.begin();
L3.erase(it++);
cout << endl;
}
注:我只测试了几种方法,剩下的方法感兴趣的朋友可以拿去自测一下,有问题及时给我指出,我改正。
二、List和vector的区别
| vector | list |
|---|---|
| 动态顺序表,一段连续空间 | 带头结点的双向循环链表 |
| 支持随机访问 | 不支持随机访问,访问某个元素效率O(N) |
| 任意位置插入和删除喜爱绿地,需要搬移元素,时间复杂度为O(N),插入时有可能需要增容(开辟新空间,拷贝元素,释放旧空间,导致效率更低) | 任意位置插入和删除效率高,不需要搬移元素,时间复杂度为O(1) |
| 底层为连续空间,不容易造成内存碎片,空间利用率高,缓存利用率高 | 底层节点动态开辟,小节点容易造成内存碎片,空间利用率低,缓存利用率低 |
| 原生态指针 | 对原生态指针(节点指针)进行封装 |
| 在插入元素时,要给所有的迭代器重新赋值,因为插入元素有可能会导致重新扩容,致使原来迭代器失效,删除时,当前迭代器需要重新赋值否则会失效 | 插入元素不会导致迭代器失效,删除元素时,只会导致当前迭代器失效,其他迭代器不受影响 |
| 需要高效存储,支持随机访问,不关心插入删除效率 | 大量插入和删除操作,不关心随机访问 |
本文通过模拟实现List的数据结构,并与Vector进行了详细的对比。包括两种数据结构的特点、应用场景及优缺点等,有助于理解不同场景下选择合适的数据结构。
1011

被折叠的 条评论
为什么被折叠?



