简述STL
程序员文章站
2024-02-11 23:37:22
...
一、STL简介
STL(standard template linbrary)
标准模板库
,是C++程序设计语言的标准程序库,是一个包罗算法与数据结构的软件框架。
使用了泛型编程
的思想,对我们常用的数据结构:顺序表、链表、树、哈希以及常用的查找、排序等算法使用模板进行了封装
,而且从运行效率以及内存使用上都基本达到了最优。
二、STL六大组件
1.容器
解释:对不同数据结构的
封装
根据数据在容器中排序特性:关联性容器、序列式容器
序列式容器:按照其加入容器的先后次序,不一定有序
关联式容器:存放的是一个一个键值对,即KV模型,键值对实际上是结构体
1.1 vector
vector(动态数组),
一段连续的空间
,当容器中的元素存放满时,扩容具体操作:动态开辟原空间大小两倍
的空间,接着将原空间的元素拷贝到新空间中,释放原空间。
1.1.1 vector的基本使用
这里演示部分接口的使用
void Testvector1()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
vector<int>::iterator it1 = v1.begin();
//while (it1 != v1.end())
//{
// cout << *it1 << " ";
// ++it1;
//}
//cout << endl;
while (it1 != v1.end())
{
if (*it1 % 2 == 0)
{
*it1 *= 2;
}
cout << *it1 << " ";
++it1;
}
cout << endl;
cout << v1.size() << endl;
cout << v1.capacity() << endl;
}
void Testvector2()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
//在末尾插入3个4
//v1.insert(v1.end(), 3, 4);
//删除区间内元素
//v1.erase(v1.begin(), v1.begin() + 2);
// assign()方法是给vector进行赋值
// 在进行赋值之前,该方法会先将vector中原有的旧元素erase掉
// 然后再将新元素插入进去
// 给vector中5个值为10的元素
//v1.assign(5, 10);
////清空元素
//v1.clear();
// resize(n,data):将vector中的元素改变到n个
// 第二个参数可以不用传,默认情况下使用缺省值
// 将vector中的元素缩小到5个,注意缩小时底层容量不变
//v1.resize(2);
//v1.resize(5);
//大于原数组元素的默认补0
//v1.resize(10);
//只扩容不初始化
//v1.reserve(30);
cout<<v1.at(2)<<endl;
vector<int>::iterator it1 = v1.begin();
while (it1 != v1.end())
{
cout << *it1 << " ";
++it1;
}
cout << endl;
}
1.1.2 模拟实现Myvector.h
template <class T>
class Myvector
{
public:
typedef T* Iterator;
typedef const T* ConstIterator;
Myvector()
:_start(0)
, _finish(0)
, _endofstorage(0)
{}
~Myvector()
{
delete[]_start;
_start = _endofstorage = _finish = 0;
}
size_t Capacity()
{
return _endofstorage - _start;
}
size_t Size()
{
return _finish - _start;
}
//扩容不初始化
void Reverse(size_t n)
{
Expand(n);
}
//扩容并且将元素初始化为0
void Resize(size_t n, const T& val = T())
{
//若n<Size(),将数组截断至n
if (n < Size())
{
_finish = _start + n;
}
else
{
//n>Capacity(),扩容并初始化,参数2可使用默认值0
if (n>Capacity())
{
Expand(n);
}
while (_finish != _start + n)
{
*_finish = val;
++_finish;
}
}
}
void Expand(size_t n)
{
//扩容思路:如果空间已满,开辟一段空间,将原有数据拷贝置新开辟的空间,在释放原有空间即可
if (n > Capacity())
{
size_t size = Size();
T *tmp = new T[n];
for (size_t i = 0; i < size; ++i)
{
tmp[i] = _start[i];
}
delete[]_start;
_start = tmp;
_finish = _start + size;
_endofstorage = _start + n;
}
}
void PushBack(const T& x)
{
//判满
if (_finish == _endofstorage)
{
//扩容
size_t capcacity = Capacity() * 2;
//只有一个元素
if (capcacity == 0)
{
capcacity = 3;
}
Expand(capcacity);
}
*_finish = x;
++_finish;
}
T& operator[](size_t pos)
{
assert(pos < Size());
return _start[pos];
}
T& at(size_t pos)//越界会抛异常
{
if (pos >= Size())
{
throw out_of_range("pos out of range");
}
return _start[pos];
}
Iterator Begin()
{
return _start;
}
Iterator End()
{
return _finish;
}
ConstIterator Begin() const
{
return _start;
}
ConstIterator End() const
{
return _finish;
}
protected:
Iterator _start;
Iterator _finish;
Iterator _endofstorage;
};
void Print_Myvector(const Myvector<int>& v1)
{
Myvector<int>::ConstIterator it1 = v1.Begin();
while (it1 != v1.End())
{
cout << *it1 << " ";
++it1;
}
cout << endl;
}
void TestMyvector()
{
Myvector<int> v1;
v1.PushBack(1);
v1.PushBack(2);
v1.PushBack(3);
v1.PushBack(4);
v1.PushBack(5);
Print_Myvector(v1);
v1.Resize(8,5);
Print_Myvector(v1);
}
1.2 list
list(
带头结点的双向循环链表
),当集合中需要进行大量的插入和删除操作时
,使用list比vector好,在任意位置进行数据插入操作的时间复杂度均为O(1)
1.2.1 list基本使用
void Testlist()
{
list<int> l1;
l1.push_back(1);
l1.push_back(2);
l1.push_back(3);
l1.push_back(4);
list<int> l2;
l2.push_back(7);
l2.push_back(8);
l2.push_back(9);
//清空list
//l1.clear();
////逆向遍历list
//list<int> ::reverse_iterator it1 = l1.rbegin();
//while (it1 != l1.rend())
//{
// cout << *it1 << " ";
// ++it1;
//}
//cout << endl;
//list的尾删
//l1.pop_back();
//头插
//l1.push_front(9);
//任意位置插入
/*list<int>::iterator pos = find(l1.begin(), l1.end(), 3);
if (pos != l1.end())
{
pos = l1.insert(pos, 0);
}*/
//l1.assign(3,10);
//cout<<l1.front() << endl;
//cout << l1.back() << endl;
//l1.remove(3);
//去除重复元素
//l1.unique();
//按升序排序
//l1.sort();
//反转链表
//l1.reverse();
//合并两个有序链表
l1.merge(l2);
list<int>::iterator it = l1.begin();
while (it != l1.end())
{
/* if (*it % 2 == 0)
{
*it *= 2;
}*/
cout << *it << " ";
++it;
}
cout << endl;
}
1.2.2 模拟实现Mylist.h
#pragma once
template <class T>
struct ListNode
{
ListNode<T>* _next;
ListNode<T>* _prev;
T _data;
ListNode(const T& data = T())
:_next(NULL)
, _prev(NULL)
, _data(data)
{}
};
template<class T,class Ref,class Ptr>
struct __ListIterator
{
typedef ListNode<T> Node;
typedef __ListIterator<T, Ref, Ptr> Self;
Node* _node;
__ListIterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &(operator*());
}
Self& operator++()
{
_node = _node->_next;
return *this;
}
Self& operator++(int)
{
Self tmp(_node);
_node = _node->_next;
return tmp;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
Self& operator--(int)
{
Self tmp(_node);
_node = _node->_prev;
return tmp;
}
bool operator==(const Self &s)const
{
return _node == s._node;
}
bool operator!=(const Self& s)const
{
return _node != s._node;
}
};
template <class T>
class Mylist
{
typedef ListNode<T> Node;
public:
typedef __ListIterator<T, T&, T*> Iterator;
typedef __ListIterator<T, const T&, const T*> ConstIterator;
Iterator Begin()
{
return _head->_next;
}
ConstIterator Begin()const
{
return _head->_next;
}
Iterator End()
{
return _head;
}
ConstIterator End() const
{
return _head;
}
Mylist()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
void PushBack(const T& x)
{
Node* tail = _head->_prev;
//连接tail newnode _head
Node* newnode = new Node(x);
tail->_next = newnode;
newnode->_prev = tail;
newnode->_next = _head;
_head->_prev = newnode;
}
void Insert(Iterator pos, const T& x)
{
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* newnode = new Node(x);
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = cur;
cur->_prev = newnode;
}
protected:
Node* _head;
};
void TestMylist()
{
Mylist<int> l1;
l1.PushBack(1);
l1.PushBack(2);
l1.PushBack(3);
l1.PushBack(4);
l1.PushBack(5);
Mylist<int>::Iterator it = l1.Begin();
while (it != l1.End())
{
cout << *it << " ";
++it;
}
cout << endl;
}