【STL】list的应用和模拟实现
来源:互联网 发布:mac 怎么隐藏侧边栏 编辑:程序博客网 时间:2024/06/05 20:27
1.认识STL
STL(标准模板库)是C++标准库的重要组成部分,共六大组件:容器,算法,迭代器,仿函数,适配器,空间配置器。此篇博客主要讲容器里的list的应用和简化版的模拟实现。
2.list的相关应用
list可以说是我们平常所写的链表,但是不完全相同,库里的list是一个用模板实现的双向循环链表。除此之外还包括迭代器的一些操作。我们先来看看list它都包含些什么:
我们先看迭代器的相关操作,迭代器是用来访问容器的。list的迭代器相当于一个指针,但其实它并不是指针,相当于对结点的一个封装。
begin():它返回的是头结点的下一个结点。因为库里的list是带头结点的链表。
end(): 它返回的是头结点,也就是说返回尾结点的下一个结点。
所以如果我们可以通过下面的代码来遍历list:
// list::begin#include <iostream>#include <list>using namespace std;int main (){ int myints[] = {75,23,65,42,13}; list<int> mylist (myints,myints+5); list<int>::iterator it; cout << "mylist contains:"; for ( it=mylist.begin() ; it != mylist.end(); it++ ) cout << " " << *it; cout << endl; return 0;}
可以看出来,迭代器总是会给一个左闭右开的区间。
rbegin()和rend()是逆序访问list的意思,看下面的测试代码你就明白了。
输出:5 4 3 2 1// list::rbegin/rend#include <iostream>#include <list>using namespace std;int main (){ list<int> mylist; for (int i=1; i<=5; i++) mylist.push_back(i); cout << "mylist contains:"; list<int>::reverse_iterator rit; for ( rit=mylist.rbegin() ; rit != mylist.rend(); ++rit ) cout << " " << *rit; cout << endl; return 0;}
当然首先它有构造函数,析构函数和赋值运算符重载,有一定C++基础的话都知道它们是用来干什么的。
这是list里面包含的一些成员方法:
assign()是赋值操作,在实际的开发中很少会用到。
void assign ( InputIterator first, InputIterator last ); //传进来两个迭代器,assign用两个迭代器之间的内容来填充对象。 void assign ( size_type n, const T& u ); //用n个u来填充对象
看以下测试用例:
// list::assign#include <iostream>#include <list>using namespace std;int main (){ list<int> first; list<int> second; first.assign (7,100); // 7 ints with value 100 second.assign (first.begin(),first.end()); // a copy of first int myints[]={1776,7,4}; first.assign (myints,myints+3); // assigning from array cout << "Size of first: " << int (first.size()) << endl; //3 cout << "Size of second: " << int (second.size()) << endl; //7 return 0;}
push_front是头插。函数原型如下:
void push_front ( const T& x );
它是如何使用的呢:
#include<iostream>#include<list>using namespace std;void TestList(){list<int> li;li.push_front(1);li.push_front(2);li.push_front(3);li.push_front(4);li.push_front(5);list<int>::iterator it;for (it = li.begin(); it != li.end(); it++){cout << *it << " ";}cout << endl;}输出:
pop_front()顾名思义,头删,也很简单。这里就不再列举测试代码了
push_back() 尾插,和头插类似。
pop_back() 尾删。
insert()插入操作,函数原型:
测试一下:iterator insert ( iterator position, const T& x ); //在position前面插入元素x void insert ( iterator position, size_type n, const T& x ); //在position前面插入n个xtemplate <class InputIterator> void insert ( iterator position, InputIterator first, InputIterator last ); //在position前面插入从first到last之间的内容
#include<iostream>#include<list>using namespace std;void TestList(){list<int> li;li.push_front(1);li.push_front(2);li.push_front(3);li.push_front(4);li.push_front(5);list<int>::iterator it;for (it = li.begin(); it != li.end(); it++){cout << *it << " ";}cout << endl;li.insert(li.begin(), 10); //前面插个10for (it = li.begin(); it != li.end(); it++){cout << *it << " ";}cout << endl;li.insert(li.end(), 3, 6); //后面插3个6cout << endl;for (it = li.begin(); it != li.end(); it++){cout << *it << " ";}cout << endl;}输出:
erase删除相关操作。函数原型:
iterator erase ( iterator position ); //删除position位置的元素并返回其后位置的迭代器。iterator erase ( iterator first, iterator last ); //删除[first,last)区间的结点,并且返回last位置的迭代器。
#include <iostream>#include <list>using namespace std;int main (){ unsigned int i; list<unsigned int> mylist; list<unsigned int>::iterator it1,it2; // set some values: for (i=1; i<10; i++) mylist.push_back(i*10); // 10 20 30 40 50 60 70 80 90 it1 = it2 = mylist.begin(); // ^^ advance (it2,6); // ^ ^ ++it1; // ^ ^ it1 = mylist.erase (it1); // 10 30 40 50 60 70 80 90 // ^ ^ it2 = mylist.erase (it2); // 10 30 40 50 60 80 90 // ^ ^ ++it1; // ^ ^ --it2; // ^ ^ mylist.erase (it1,it2); // 10 30 60 80 90 // ^ cout << "mylist contains:"; for (it1=mylist.begin(); it1!=mylist.end(); ++it1) cout << " " << *it1; cout << endl; return 0;}
swap()设计到容器适配器,我们先不看它。
clear(),删除链表中的全部结点。很简单,这里不再测试。
这是list的容器适配器部分的内容。
splice() //往一个list里的某个位置插入另一个list的元素。
// splicing lists#include <iostream>#include <list>using namespace std;int main (){ list<int> mylist1, mylist2; list<int>::iterator it; // set some initial values: for (int i=1; i<=4; i++) mylist1.push_back(i); // mylist1: 1 2 3 4 for (int i=1; i<=3; i++) mylist2.push_back(i*10); // mylist2: 10 20 30 it = mylist1.begin(); ++it; // points to 2 mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4 // mylist2 (empty) // "it" still points to 2 (the 5th element) mylist2.splice (mylist2.begin(),mylist1, it); // mylist1: 1 10 20 30 3 4 // mylist2: 2 // "it" is now invalid. it = mylist1.begin(); advance(it,3); // "it" points now to 30 mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end()); // mylist1: 30 3 4 1 10 20 cout << "mylist1 contains:"; for (it=mylist1.begin(); it!=mylist1.end(); it++) cout << " " << *it; cout << "\nmylist2 contains:"; for (it=mylist2.begin(); it!=mylist2.end(); it++) cout << " " << *it; cout << endl; return 0;}
remove()函数原型:
void remove ( const T& value ); //找出value然后删除remove_if()函数原型:
void remove_if ( Predicate pred ); //条件删除,参数是条件,在特定删除是特别方便,比如删除奇数或者删除10以下的数
unique()函数原型:// list::remove_if#include <iostream>#include <list>using namespace std;// a predicate implemented as a function:bool single_digit (const int& value) { return (value<10); } //判断数据是否小于10// a predicate implemented as a class:class is_odd{public: bool operator() (const int& value) {return (value%2)==1; } //判断是否是奇数};int main (){ int myints[]= {15,36,7,17,20,39,4,1}; list<int> mylist (myints,myints+8); // 15 36 7 17 20 39 4 1 mylist.remove_if (single_digit); // 15 36 17 20 39 mylist.remove_if (is_odd()); // 36 20 cout << "mylist contains:"; for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it) cout << " " << *it; cout << endl; return 0;}
void unique ( ); //去掉重复值template <class BinaryPredicate> void unique ( BinaryPredicate binary_pred ); //条件去重,比如浮点数整数部分相同的删除掉,或者两数相差小于5的删除掉
// list::unique#include <iostream>#include <cmath>#include <list>using namespace std;// a binary predicate implemented as a function:bool same_integral_part (double first, double second){ return ( int(first)==int(second) ); }// a binary predicate implemented as a class:class is_near{public: bool operator() (double first, double second) { return (fabs(first-second)<5.0); }};int main (){ double mydoubles[]={ 12.15, 2.72, 73.0, 12.77, 3.14, 12.77, 73.35, 72.25, 15.3, 72.25 }; list<double> mylist (mydoubles,mydoubles+10); mylist.sort(); // 2.72, 3.14, 12.15, 12.77, 12.77, // 15.3, 72.25, 72.25, 73.0, 73.35 mylist.unique(); // 2.72, 3.14, 12.15, 12.77 // 15.3, 72.25, 73.0, 73.35 mylist.unique (same_integral_part); // 2.72, 3.14, 12.15 // 15.3, 72.25, 73.0 mylist.unique (is_near()); // 2.72, 12.15, 72.25 cout << "mylist contains:"; for (list<double>::iterator it=mylist.begin(); it!=mylist.end(); ++it) cout << " " << *it; cout << endl; return 0;}
注意:unique是在有序的前提下进行去重。所以,在使用它之前最好先对list排一下序。
merge()函数原型:
void merge ( list<T,Allocator>& x ); //将x 和对象进行合并,合并完成后x里数据全部被删除掉template <class Compare> void merge ( list<T,Allocator>& x, Compare comp );
sort()函数原型:
void sort ( );template <class Compare> void sort ( Compare comp );
对list中的元素进行排序。
reverse()函数原型:
void reverse ( );
很简单,对list进行逆序。
front()返回头结点的数据。
back()返回尾结点的数据。
3.简单模拟实现list
#pragma once#include<iostream>#include<cassert>using namespace std;template <class T>struct LinkNode{typedef LinkNode<T> node;LinkNode(T n=0):_data(n), _prev(0), _next(0){}T _data;node * _prev;node * _next;};template <class T,class Ptr,class Ref>class LinkIterator{public:typedef LinkIterator<T, Ptr, Ref> Self;typedef LinkIterator<T, T*, T&> Iterator;typedef LinkNode<T> node;LinkIterator(node* x):_node(x){}LinkIterator(){}LinkIterator(const Self& it){_node = it._node;}bool operator==(const Self& it){return _node == it._node;}bool operator!=(const Self& it){return _node != it._node;}Ref operator*(){return _node->_data;}Ptr operator->(){return &(_node->_data);}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;}node* _node;};template <class T>class Link{public:typedef LinkIterator<T, T*, T&> Iterator;typedef Link<T> link;typedef LinkNode<T> node;typedef node* node_type;Link():_head(new node(T())){_head->_next = _head;_head->_prev = _head;}~Link(){Clear();delete _head;_head = NULL;}/*****************插入相关操作**********************/void PushBack(T x) //尾插{/*node* NewNode = BuyNewNode(x);node* tmp = _head->_prev;NewNode->_prev = tmp;NewNode->_next = _head;tmp->_next = NewNode;_head->_prev = NewNode;*/Insert(End(), x);}void PushFront(T x) //头插{Insert(Begin(), x);}Iterator Insert(Iterator pos, const T& x) // 在pos前插入值t的元素,返回新添加元素的迭代器 {node_type NewNode = BuyNewNode(x);node_type cur = pos._node;NewNode->_next = cur;cur->_prev->_next = NewNode;NewNode->_prev = cur->_prev;cur->_prev = NewNode;return Iterator(NewNode);}void Insert(Iterator pos, size_t n, const T &t)//在pos前插入n个值为t的元素 {for (size_t i = 0; i < n; i++){Insert(pos, t);}}void Insert(Iterator pos, Iterator b, Iterator e)//在pos前插入[b,e)范围的元素{for (Iterator tmp = b; tmp != e; tmp++){Insert(pos, tmp._node->_data);}}node* BuyNewNode(T x=0){node*tmp = new node(x);tmp->_next = tmp;tmp->_prev = tmp;return tmp;}/**********删除相关操作*******************/Iterator Erase(Iterator it)//删除it所指向的元素,返回所删除元素的下一个元素对应的迭代器 {assert(it != End());node_type cur = it._node;node_type del = cur;cur = cur->_next;cur->_prev = del->_prev;del->_prev->_next = cur;delete del;del = NULL;return Iterator(cur);}void Clear()//删除容器内的所有元素 {node_type cur = _head->_next;while (cur != _head){node* del = cur;cur = cur->_next;delete del;del = NULL;}}void PopBack()//删除容器内最后一个有效的元素 {Erase(--End());}void PopFront()//删除容器内第一个有效的元素 {Erase(Begin());}/***************访问相关*******************/Iterator Begin(){return Iterator(_head->_next);}Iterator End(){return Iterator(_head);}T& Front(){return _head->_next->_data;}T& Back(){return _head->_prev->_data;}bool Empty() const{return _head->_next == _head;}size_t Size(){size_t count = 0;for (Iterator it = Begin(); it != End(); it++){count++;}return count;}private:node_type _head;};测试用代码:
#include"Link.h"void TestLink(){Link<int> l;l.PushBack(1); //测试尾插,插入函数l.PushBack(2);Link<int> l2;l2.PushFront(1); //测试头插l2.PushFront(2);Link<int>::Iterator it;for (it = l.Begin(); it != l.End(); it++) //测试迭代器{cout << *it << " ";}cout << endl;for (it = l2.Begin(); it != l2.End(); it++){cout << *it << " ";}cout << endl;l2.Insert(l2.Begin(), 4, 1); //测试重载的插入函数for (it = l2.Begin(); it != l2.End(); it++){cout << *it << " ";}cout << endl;l.Insert(l.Begin(), l2.Begin(), l2.End()); //测试重载的插入函数for (it = l.Begin(); it != l.End(); it++) {cout << *it << " ";}cout << endl;l.Erase(--l.End());//测试删除函数for (it = l.Begin(); it != l.End(); it++){cout << *it << " ";}cout << endl;cout << l.Front() << endl; //测试访头函数cout << l.Back() << endl; //测试访尾函数cout << l.Size() << endl; //测试容器大小函数}
- 【STL】list的应用和模拟实现
- 【STL】 list的应用及模拟实现
- 【STL】list的应用模拟实现
- STL库中的list的使用和模拟实现
- <STL>模拟实现List
- STL-模拟实现List
- 【STL】模拟实现list
- 【STL】迭代器与List的模拟实现
- 【STL】list迭代器的模拟实现
- 数据结构::模拟STL实现list
- 模拟实现STL中的list
- 模拟实现STL中的list
- STL模拟实现List+迭代器
- STL容器中list与迭代器iterator的模拟实现
- 用List模拟实现STL下的queue队列
- STL中list的使用及模拟实现
- STL模拟实现1.0 -- list和iterator模拟实现和简单分析
- STL库list的模拟
- Leetcode 102. Binary Tree Level Order Traversal
- HDU 1059 Dividing(dp多重背包)
- OpenCV 形态学膨胀——dilate函数
- 函数的几个使用示例
- href="javascript:void(0)"
- 【STL】list的应用和模拟实现
- OpenCV 形态学腐蚀——erode函数
- spring 源码如何导入到eclipse
- mysql创建 学生表、课程表、分数表、教师表
- MVP+Retrofit+RxJava组合使用
- 计算机算法设计与分析作业01:分治法求解大数乘法+L型骨牌的棋盘覆盖问题
- sass实战演练07 - 做一个有逼格的table(1)
- SwipeRefreshLayout 设置下拉刷新的距离高度
- STL源码学习----lower_bound和upper_bound算法