数据结构与算法:STL容器

来源:互联网 发布:ipsec dh算法 编辑:程序博客网 时间:2024/06/04 17:45

STL(Standard Template Library)是一个C++领域中,用模板技术实现的数据结构和算法库,其中的vector、list、stack、queue等结构不仅拥有更强大的功能,还有了更高的安全性。它体现了泛型编程的思想,具有高度的可重用行、高性能、高移植性。

  • 什么是泛化编程
  • vector与list
  • 使用两个栈模拟队列操作
    • 引申如何使用两个队列实现栈

什么是泛化编程

泛化编程(Generic Programming)的目的是为了发明一种语言机制,能够帮助实现一个通用的标准容器库。通用的标准容器库是指能够实现这样一种功能:例如,用一个List类存放所有可能类型的对象,而泛型编程可以让程序员编写完全一般化并可重复使用的算法,其效率与针对某特定数据类型而设计的算法相同。泛型与模板类似,指具有在多种数据类型上皆可操作的含义。

STL巨大,而且可以扩充,它包含很多计算机基本算法和数据结构,而且将算法与数据结构完全分离,其中算法是泛型的,不与任何特定数据结构或对象类型系在一起。

vector与list

vector为存储的对象分配一块连续的地址空间,对vector中的元素随机访问效率很高。在vector中插入或者删除某个元素,需要将现有元素进行复制、 
移动。如果vector中存储的对象很大,或者构造函数复杂,则在对现有元素进行拷贝时开销较大,因为拷贝对象要调用拷贝构造函数。对于简单的小对象来说,vector的效率优于list。vector在每次扩张容量的时候,将容量扩展2倍,这样对于小对象来说,效率是很高的。

list表示非连续的内存区域,并通过一对指向首尾元素的指针双向链接起来从而允许向前和向后两个方向进行遍历,list中的对象是离散存储的。在list的任意位置插入与删除元素的效率都很高,指针必须被重新赋值,但是不需要拷贝元素来实现移动。它对随机访问的支持并不好,访问一个元素需要遍历中间的元素,另外每个元素还有两个指针的额外空间开销,随机访问某个元素需要遍历list。在list中插入元素,尤其是在首尾插入元素,效率很高,只需要改变元素的指针即可。

vector内部使用顺序存储,访问速度快,但是删除数据比较耗费性能。list内部使用链式存储,访问速度慢,但是删除数据比较快。

一般应遵循下面的原则: 
(1)需要高效的随机存取,而不在乎插入和删除的效率,使用vector。 
(2)需要大量的插入和删除,而不关心随机存取,则应使用list 
(3)需要随机存取,而且关心两段数据的插入和删除,则应使用deque(双端队列)。

使用两个栈模拟队列操作

题目要求用两个栈来模拟队列,栈A与栈B模拟队列Q,A为插入栈,B为弹出栈,以实现队列Q。

假设A和B都为空,可以认为栈A提供入队列的功能,栈B提供出队列的功能。 
入队列:入栈A 
出队列分两种情况考虑: 
(1)如果栈B不为空,则直接弹出栈B的数据 
(2)如果栈B为空,则一次弹出栈A的数据,放入栈B中,再弹出栈B的数据。

#include<iostream>#include<stack>using namespace std;template< typename T >class QueueByDoubleStack{    public:         size_t size();        bool empty();        void push( T t );        void pop();        T top();    private:        stack<T> s1;        stack<T> s2;};template< typename T >size_t QueueByDoubleStack<T>::size(){    return s1.size() + s2.size();}template<typename T>bool QueueByDoubleStack<T>::empty(){    return s1.empty() && s2.empty();}template<typename T>void QueueByDoubleStack<T>::push( T t ){    s1.push(t);}template<typename T>void QueueByDoubleStack<T>::pop(){    if( s2.empty() )    {        while( !s1.empty() )        {            s2.push( s1.top() );            s1.pop();        }    }    s2.pop();}template<typename T>T QueueByDoubleStack<T>::top(){    if( s2.empty() )    {        while( !s1.empty() )        {            s2.push( s1.top() );            s1.pop();        }    }    return s2.top();}int main(){    QueueByDoubleStack<int> q;    for(int i=0; i<10; ++i )    {        q.push(i);    }    while(!q.empty())    {        cout << q.top() << ' ';        q.pop();    }    cout << endl;    return 0;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85

引申:如何使用两个队列实现栈

可以采用两种方法实现,入栈:所有元素依次存入队列q1。例如,将A、B、C、D四个元素入栈,从队列尾部到队列首部依次为D、C、B、A,出栈的时候判断栈元素个数是否为1,如果为1,则队列q1出列;如果不为1,则队列q1所有元素出队列,入队列q2,最后一个元素不入队列B,输出该元素,队列q2所有元素入队列q1.例如,将D、C、B、A出列,D输出来,C、B、A入队列q2,最后返回到队列q1中,实现了后进先出