1. 程式人生 > 實用技巧 >pytorch實現 | Deformable Convolutional Networks | CVPR | 2017

pytorch實現 | Deformable Convolutional Networks | CVPR | 2017

STL

stl基本概念

STL(Standard Template Library,標準模板庫),是惠普實驗室開發的一系列軟體的統稱。現在主要出現在 c++中,但是在引入 c++之前該技術已經存在很長時間了。 STL 從廣義上分為: 容器(container) 演算法(algorithm) 迭代器(iterator),容器和演算法之間通過迭代器進行無縫連線。STL 幾乎所有的程式碼都採用了模板類或者模板函式,這相比傳統的由函式和類組成的庫來說提供了更好的程式碼重用機會。STL(Standard Template Library)標準模板庫,在我們 c++標準程式庫中隸屬於 STL 的佔到了 80%以上。

stl六大元件

STL提供了六大元件,彼此之間可以組合套用,這六大元件分別是:容器、演算法、迭代器、仿函式、介面卡(配接器)、空間配置器。

容器:各種資料結構,如vector、list、deque、set、map等,用來存放資料,從實現角度來看,STL容器是一種class template。

演算法:各種常用的演算法,如sort、find、copy、for_each。從實現的角度來看,STL演算法是一種function tempalte.

迭代器:扮演了容器與演算法之間的膠合劑,共有五種型別,從實現角度來看,迭代器是一種將operator* , operator-> , operator++,operator--等指標相關操作予以過載的class template. 所有STL容器都附帶有自己專屬的迭代器,只有容器的設計者才知道如何遍歷自己的元素。原生指標(native pointer)也是一種迭代器。

仿函式:行為類似函式,可作為演算法的某種策略。從實現角度來看,仿函式是一種過載了operator()的class 或者class template

介面卡:一種用來修飾容器或者仿函式或迭代器介面的東西。

空間配置器:負責空間的配置與管理。從實現角度看,配置器是一個實現了動態空間配置、空間管理、空間釋放的class tempalte.

STL六大元件的互動關係,容器通過空間配置器取得資料儲存空間,演算法通過迭代器儲存容器中的內容,仿函式可以協助演算法完成不同的策略的變化,介面卡可以修飾仿函式。

2. STL三大元件

2.1 容器

容器,置物之所也。

研究資料的特定排列方式,以利於搜尋或排序或其他特殊目的,這一門學科我們稱為資料結構。大學資訊類相關專業裡面,與程式設計最有直接關係的學科,首推資料結構與演算法。幾乎可以說,任何特定的資料結構都是為了實現某種特定的演算法。STL容器就是將運用最廣泛的一些資料結構實現出來。

常用的資料結構:陣列(array),連結串列(list),tree(樹),棧(stack),佇列(queue),集合(set),對映表(map),根據資料在容器中的排列特性,這些資料分為序列式容器關聯式容器兩種。

Ø 序列式容器強調值的排序,序列式容器中的每個元素均有固定的位置,除非用刪除或插入的操作改變這個位置。Vector容器、Deque容器、List容器等。

Ø 關聯式容器是非線性的樹結構,更準確的說是二叉樹結構。各元素之間沒有嚴格的物理上的順序關係,也就是說元素在容器中並沒有儲存元素置入容器時的邏輯順序。關聯式容器另一個顯著特點是:在值中選擇一個值作為關鍵字key,這個關鍵字對值起到索引的作用,方便查詢。Set/multiset容器 Map/multimap容器

2.2 演算法

演算法,問題之解法也。

以有限的步驟,解決邏輯或數學上的問題,這一門學科我們叫做演算法(Algorithms).

廣義而言,我們所編寫的每個程式都是一個演算法,其中的每個函式也都是一個演算法,畢竟它們都是用來解決或大或小的邏輯問題或數學問題。STL收錄的演算法經過了數學上的效能分析與證明,是極具複用價值的,包括常用的排序,查詢等等。特定的演算法往往搭配特定的資料結構,演算法與資料結構相輔相成。

演算法分為:質變演算法非質變演算法

質變演算法:是指運算過程中會更改區間內的元素的內容。例如拷貝,替換,刪除等等

非質變演算法:是指運算過程中不會更改區間內的元素內容,例如查詢、計數、遍歷、尋找極值等等

再好的程式設計技巧,也無法讓一個笨拙的演算法起死回生。

2.3 迭代器

迭代器(iterator)是一種抽象的設計概念,現實程式語言中並沒有直接對應於這個概念的實物。在<<Design Patterns>>一書中提供了23中設計模式的完整描述,其中iterator模式定義如下:提供一種方法,使之能夠依序尋訪某個容器所含的各個元素,而又無需暴露該容器的內部表示方式。

迭代器的設計思維-STL的關鍵所在,STL的中心思想在於將容器(container)和演算法(algorithms)分開,彼此獨立設計,最後再一貼膠著劑將他們撮合在一起。從技術角度來看,容器和演算法的泛型化並不困難,c++的class template和function template可分別達到目標,如果設計出兩這個之間的良好的膠著劑,才是大難題。

迭代器的種類:

輸入迭代器 提供對資料的只讀訪問 只讀,支援++、==、!=
輸出迭代器 提供對資料的只寫訪問 只寫,支援++
前向迭代器 提供讀寫操作,並能向前推進迭代器 讀寫,支援++、==、!=
雙向迭代器 提供讀寫操作,並能向前和向後操作 讀寫,支援++、--,
隨機訪問迭代器 提供讀寫操作,並能以跳躍的方式訪問容器的任意資料,是功能最強的迭代器 讀寫,支援++、--、[n]、-n、<、<=、>、>=

2.3 案例

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

//STL 中的容器 演算法 迭代器
void test01(){
vector<int> v; //STL 中的標準容器之一 :動態陣列
v.push_back(1); //vector 容器提供的插入資料的方法
v.push_back(5);
v.push_back(3);
v.push_back(7);
//迭代器
vector<int>::iterator pStart = v.begin(); //vector 容器提供了 begin()方法 返回指向第一個元素的迭代器
vector<int>::iterator pEnd = v.end(); //vector 容器提供了 end()方法 返回指向最後一個元素下一個位置的迭代器
//通過迭代器遍歷
while (pStart != pEnd){
cout << *pStart << " ";
pStart++;
}
cout << endl;
}
//STL 容器不單單可以儲存基礎資料型別,也可以儲存類物件
class Teacher
{
public:
Teacher(int age) :age(age){};
~Teacher(){};
public:
int age;
};
void test02(){
vector<Teacher> v; //儲存 Teacher 型別資料的容器
Teacher t1(10), t2(20), t3(30);
v.push_back(t1);
v.push_back(t2);
v.push_back(t3);
vector<Teacher>::iterator pStart = v.begin();
vector<Teacher>::iterator pEnd = v.end();
//通過迭代器遍歷
while (pStart != pEnd){
cout << pStart->age << " ";
pStart++;
}
cout << endl;
}
//儲存 Teacher 型別指標
void test03(){
vector<Teacher*> v; //儲存 Teacher 型別指標
Teacher* t1 = new Teacher(10);
Teacher* t2 = new Teacher(20);
Teacher* t3 = new Teacher(30);
v.push_back(t1);
v.push_back(t2);
v.push_back(t3);
//拿到容器迭代器
vector<Teacher*>::iterator pStart = v.begin();
vector<Teacher*>::iterator pEnd = v.end();
//通過迭代器遍歷
while (pStart != pEnd){
cout << (*pStart)->age << " ";
pStart++;
}
cout << endl;
}
//容器巢狀容器 難點(不理解,可以跳過)
void test04()
{
vector< vector<int> > v;
vector<int>v1;
vector<int>v2;
vector<int>v3;

for (int i = 0; i < 5;i++)
{
v1.push_back(i);
v2.push_back(i * 10);
v3.push_back(i * 100);
}
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);

for (vector< vector<int> >::iterator it = v.begin(); it != v.end();it++)
{
for (vector<int>::iterator subIt = (*it).begin(); subIt != (*it).end(); subIt ++)
{
cout << *subIt << " ";
}
cout << endl;
}
}
int main(){
//test01();
//test02();
//test03();
test04();
system("pause");
return EXIT_SUCCESS;
}