Ⅶ 类模板与STL编程 ①

1.类模板的概念

1.1 函数模板的回顾

template <class T1, class T2>
T1 add(T1 x, T2 y)
{
    return x+y;
}
int main()
{
    cout << add(9, ‘A’) << endl;    //两种表达形式
    cout << add<int, char>(9, ‘A’) << endl;
}

1.2 类模板的定义

template <class T, int size>   //class:参数化类型  int:普通类型

class CSafeArray            //既然上面出现了class,接下来就要对class进行定义       
{
    T a[size];
public:
    CSafeArray()      //初始化
    {
        for(int i=0; i<size; i++)
            a[i] = i;
    } 
    T &operator[](int i)  //函数模板:类模板中的成员函数
    {
        if(i<0 || i>size-1)
        {
            cout << "Index value of " << i << " is out-of-bounds.\n";
            exit(1);
        }
        return a[i];
    }
};

 

//在类外面定义
template <class T, int size> 
class CSafeArray
{
    T a[size];
public:
    CSafeArray()
    {
        for(int i=0; i<size; i++)
            a[i] = i;
    } 
    T &operator[](int i);
};

template <class T, int size>   //写在外面的话就要把这个头加上
T &CSafeArray<T, size>::operator[](int i)  //再加上作用域
{
    if(i<0 || i>size-1)
    {
        cout << "Index value of ";
        cout << i << " is out-of-bounds.\n";
        exit(1);
    }
    return a[i];
}

1.3 类模板的实例化

和函数的实参与形参结合类似

const int SIZE = 10; 
CSafeArray<int, SIZE> intOb;   //带入即可

cout << "Integer array: "; 
for(int i=0; i<SIZE; i++) 
    intOb[i] = i;     //其实是个操作符
for(int i=0; i<SIZE; i++) 
    cout << intOb[i] << " "; 
cout << '\n';

1.4 带默认参数的类模板

与带默认形参的函数类似

template <class T=int, int size=10>  //一开始有了默认的
class CSafeArray{};
//使用的时候可以啥也不写
CSafeArray <>intOb;

 

2.类模板的应用

2.1 顺序堆栈类模板(先进后出)

const int SIZE = 10;
template <class ST>
class stack
{
    ST s[SIZE];
    int top;
public:
    stack()
    {
        top = 0;
    }
    void Push(ST ob);
    ST Pop();
};

// Push an object.
template <class ST>  //在外面的话,每个都要加
void stack<ST>::Push(ST ob)
{
    if(top==SIZE)
    {
        cout << "Stack is full.\n";
        return;
    }
    s[top] = ob;
    top++;
}

int main()
{
    int i;
    stack<char> cs;
    cs.Push('a');
    cs.Push('b');
    cs.Push('c');
    for(i=0; i<3; i++)
        cout << "Pop s1: " << cs.Pop() << "\n";
}

2.2 顺序队列类模板(先进先出)

2.3 链表类模板

template <class ElemType> 
struct LNode
{
    ElemType data;
    LNode *next;
    LNode(ElemType _data=0, LNode *_next=NULL)
    {
        data = _data;
        next = _next;
    }
};

template <class ElemType> 
class LinkList
{
    LNode<ElemType> *head;
    LNode<ElemType> * rear;
    int size;
public:
    LinkList(ElemType *data=NULL, int n=0);
    ~LinkList();
    void Clear();
    bool IsEmpty();
    int GetLength();
    … void Print();
};

 

3.STL编程

3.1 STL简介

 

 

 

 

◼ 时间复杂度

 

 

 3.2 STL容器

3.2.1 定义

 一个通用的数据结构,可以处理不同的数据类型

3.2.2 容器

① 顺序容器(sequence)

◼ 特点:来一个进一个,与值无关,不会自动排序

◼ 向量容器(vector)

 

 

 # 栗子

#include <vector>

int main()
{
    vector<int> v;    //或者v(6,1),即一共六个元素,初始化为1
    for (int i=0; i<6; ++i)
        v.push_back(i);   //或者v[i]=i;
    
    for (int i=0; i<3; ++i)
        v.pop_back();
    
    for (int i=0; i<v.size(); ++i)
        cout << v[i] << ' ';
    cout << endl;
}

# 复杂度:随机存取+在末尾插入和删除:O(1)

# 适用范围:快速存取&不频繁的插入删除的场合

◼ 列表容器(list)

 

 

 # 栗子🌰

#include <list>
#include <vector>
#include <iostream>

using namespace std;

int main ()
{
    list<int> ml;
    list<int>::iterator it;  

    for (int i=1; i<=5; i++)
        ml.push_back(i);   //1,2,3,4,5
    it = ml.begin();
    ++it;

    ml.insert (it,10);  //在所指定元素之前
                        //1,10,2,3,4,5    
    ml.insert (it,2,20);//it仍然指的是2
                        //1,10,20,20,2,3,4,5
    --it;  //指向第二个20

    vector<int> mv (2,30);  //30,30
    ml.insert (it,mv.begin(),mv.end()); //1,10,20,30,30,20,2,3,4,5

    for (it=ml.begin(); it!=ml.end(); it++)
       cout << " " << *it;
    cout << endl;
}

# 迭代器

## 定义:特殊的指针,在顺序容器或关联容器中,能对每个元素进行连续存取的对象

## 格式: 容器名<数据类型>::iterator 迭代器名

## 作用:提供一种一般化的方法,对不同类型容器中的元素进行访问

 

 

 

## 非标准迭代器

const_iterator

reverse_iterator 

const_reverse_iterator

# 还有一个栗子

#include <list>
#include <vector>
#include <iostream>

using namespace std;

int main ()
{
    list<int> first, second;

    first.push_back (1);
    first.push_back (2);
    first.push_back (9);

    second.push_back (3);
    second.push_back (7);
    second.push_back (4);

    first.sort();
    second.sort();

    first.merge(second);    //把二倒入一里,二空了,一里面的顺序是升序
    second.push_back (5);
    first.merge(second);
                                  //it就是指针嘛
    for (list<int>::iterator it=first.begin(); it!=first.end(); ++it)
        cout << *it << " ";
    cout << endl;
}

 

 

 ◼ 双端队列容器(deque)

 

 

# 栗子 

#include <deque>
#include <string>
#include <iostream>
using namespace std;

int main()
{
    deque<string> ds;
    ds.assign (3,string("Hello"));   //三个hello 
    ds.push_back ("] last");  //在头部增加一个元素
    ds.push_front ("first [");  //在尾部增加一个元素
    
    for (int i=0; i<ds.size(); ++i)
        cout << ds[i] << " ";
    cout << endl;
    
    ds.pop_front();  //删除第一个元素
    ds.pop_back();  //删除最后一个个元素
    
    for (int i=1; i<ds.size(); ++i)
        ds[i] = "another " + ds[i];   //在前面加hello
    
    ds.resize (4, "Hello C++");  //更改容器大小,改为四,在最后加C++一句
    
    for (int i=0; i<ds.size(); ++i)
        cout << ds[i] << " ";
    cout << endl;
}

输出:first [ Hello Hello Hello ] last
Hello another Hello another Hello Hello C++

 

 

 ② 关联容器(sorted associative)

◼ 特点:元素的添加或插入与元素的值相关

◼ 集合(set)

#include <set>
int main ()
{
    set<int> myset;
    set<int>::iterator it;
    pair<set<int>::iterator,bool> ret;
    
    for (int i=1; i<=5; i++)
        myset.insert(i*10);
    ret = myset.insert(20);
    
    if (ret.second==false)
        it=ret.first;
   
    myset.insert (it,25);
    myset.insert (it,24);
    myset.insert (it,26);
    int myints[]= {5,10,15};
    myset.insert (myints,myints+3);
    
    for (it=myset.begin(); it!=myset.end(); it++)
        cout << " " << *it;
    cout << endl;
}

◼ 映射(map)

#include <map>
int main()
{
    map<char, int> m;   //一对
    map<char, int>::iterator p;
    int i;
    char ch;
    
    for(i=0; i<26; i++)
        m.insert(pair<char, int>('A'+i, 65+i));
    cout << "Enter key: ";
    cin >> ch;
    
    p = m.find(ch);
    if(p != m.end())
        cout << "Its ASCII value is " << p->second;
    else
        cout << "Key not in map.\n";
}

◼ 多映射(multimap) (允许有重复的元素)

#include <map>
int main()
{
    multimap<string,string> dict;
    multimap<string,string>::iterator p;
    
    dict.insert(make_pair("smart","聪明的"));
    dict.insert(make_pair("smart","漂亮的"));
    dict.insert(make_pair("smart","巧妙的"));
    dict.insert(make_pair("smart","敏捷的"));
    dict.insert(make_pair("wise","聪明的"));
    dict.insert(make_pair("clever","聪明的"));
    
    for (p = dict.begin(); p != dict.end(); ++p)
        cout << p->first.c_str() << "\t"<< p->second << endl;
    string word("smart");
    
    for (p = dict.lower_bound(word); p != dict.upper_bound(word); ++p)
        cout << " " << p->second << endl;
    word = ("聪明的");
    
    for (p = dict.begin(); p != dict.end(); ++p)
        if (p->second == word)
        {
            cout << " " << p->first << endl;
        }
}

③ 容器适配器(adaptors)

◼ 由顺序容器转换出的新容器:list→queue;vector→stack

◼ 队列 queue

#include <queue>
int main ()
{
    queue<int> myqueue;
    int myint;
    cout << "Please enter some integers (enter 0 to end):\n";
    do
    {
        cin >> myint;
        myqueue.push (myint);  //入列
    }
    while (myint);
    
    while (!myqueue.empty())
    {
        cout << myqueue.front() << " ";  //出列
        myqueue.pop();   //去顶
    }
}
#include <queue>
int main()
{
    priority_queue<float> q;
    q.push(66.6);
    q.push(22.2);
    q.push(44.4);
    cout << q.top() << ' ';
    q.pop();
    
    cout << q.top() << endl;
    q.pop();
    q.push(11.1);
    q.push(55.5);
    q.push(33.3);
    q.pop();
    while (!q.empty())
    {
        cout << q.top() << ' '; //不是push了
        q.pop();
    }
    cout << endl;
}

◼ 堆栈 stack

#include <stack>
int main()
{
    stack<int> st;
    st.push(1);
    st.push(2);
    st.push(3);
    cout << st.top() << ' ';
    st.pop() ;
    cout << st.top() << ' ';
    st.pop() ;
    st.top() = 77;
    st.push(4);
    st.push(5);
    st.pop() ;
    while (!st.empty())
    {
        cout << st.top() << ' ';
        st.pop() ;
    }
    cout << endl;
}

◼ 特殊容器(special)

 

# 位集bitset

## 灵活对二进制位进行操作

## 整型到二进制的转换

## 位的直接访问和设置

#include <bitset>
#include <limits>
#include <iostream>
using namespace std;

int main()
{
    cout << "267 as binary short: "
         << bitset<numeric_limits<unsigned short>::digits>(267) << endl;
    cout << "267 as binary long: "
         << bitset<numeric_limits<unsigned long>::digits>(267) << endl;
    cout << "10,000,000 with 24 bits: "
         << bitset<24>(1e7)<< endl;
}

267 as binary short: 0000000100001011
267 as binary long: 00000000000000000000000100001011
10,000,000 with 24 bits: 100110001001011010000000

#include <bitset>
#include <limits>
#include <iostream>
using namespace std;

int main()
{
    bitset<16>flags(0xFFF0);

    flags[2] = true;
    flags[3] = flags[2];
    flags[2].flip();

    if (flags[13])
        flags [0] = ~flags [2];
    cout << flags << endl;
}

1111111111111001

 

posted @ 2020-05-10 16:15  ananasaa  阅读(163)  评论(0编辑  收藏  举报