C#用いてSystem.Collectionクラスについて書いたページ(これ)がありますが、そのとき「STLにもスタックやキューがあったな」というのを思い出して、STLを使ってみることを思いつきました。 実はSTLを使うのは初めてです。 そのため、浅はかな知識で書いていることをご了承ください。
.NET Frameworkにおいて、スタックやキューはクラス化されたものがSystem.Collection名前空間に存在しますが、STLにもスタック (stack)やキュー(queue)といったものが用意されているので、それを使ってみることにします。 STLについては何も知らないので、ここでは STLが何であるかという説明はおいておきます。
STLのstackは.NET FrameworkのStackとは異なり、Popしてもアイテムは返されません。 Popは最後に追加したアイテムを取り出して破棄します。 このとき Popする前にtop()関数を用いてアイテムを参照することはできます。 Pushの動作は変わりありません。 次のコードはSTLのstackを int型で用いた例です。 スタックの動作についてはこちらを参考にしてください
#include <iostream> #include <stack> using namespace std; int main() { stack<int> st; int i; cout << "Pusshed "; for ( i = 0; i < 10; i++ ) { cout << i << ", "; st.push( i ); } cout << endl << "Popped "; for ( i = 0; i < 10; i++ ) { cout << (int)st.top() << ", "; st.pop(); } cout << endl; return 0; }#includeusing namespace std; int main() { stack st; int i; cout << "Pusshed "; for ( i = 0; i < 10; i++ ) { cout << i << ", "; st.push( i ); } cout << endl << "Popped "; for ( i = 0; i < 10; i++ ) { cout << (int)st.top() << ", "; st.pop(); } cout << endl; return 0; }]]>
Pusshed 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, Popped 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, Press any key to continue
.NET FrameworkのQueueはEnqueue()とDequeue()でアイテムを入れたり出したりしていたのですが、STLのqueueでは stackのようにpop()とpush()を使います。 また、.NET Frameworkと異なり、front()とback()により先頭と末尾の両方のアイテムを参照することができます。 Countプロパティに相当するものに、サイズを取得するためのsize()も存在します(stackにも存在します)。 次のコードはSTLのqueueをint型で用いた例です。 キューの動作についてはこちらを参考にしてください、
#include <iostream> #include <queue> using namespace std; int main() { queue<int> qu; int i; cout << "Pusshed "; for ( i = 0; i < 10; i++ ) { cout << i << ", "; qu.push( i ); } cout << endl; cout << "Front of queue is " << qu.front() << endl; cout << "Back of queue is " << qu.back() << endl; cout << "Size of queue is " << qu.size() << endl; cout << "Popped "; for ( i = 0; i < 10; i++ ) { cout << (int)qu.front() << ", "; qu.pop(); } cout << endl; return 0; }#includeusing namespace std; int main() { queue qu; int i; cout << "Pusshed "; for ( i = 0; i < 10; i++ ) { cout << i << ", "; qu.push( i ); } cout << endl; cout << "Front of queue is " << qu.front() << endl; cout << "Back of queue is " << qu.back() << endl; cout << "Size of queue is " << qu.size() << endl; cout << "Popped "; for ( i = 0; i < 10; i++ ) { cout << (int)qu.front() << ", "; qu.pop(); } cout << endl; return 0; }]]>
Pusshed 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, Front of queue is 0 Back of queue is 9 Size of queue is 10 Popped 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, Press any key to continue
STLにはstackやqueueのほかにもさまざまなテンプレートクラスが存在します。 そのうちのdequeは.NET Frameworkには相当するものがないもので、一見するとqueueと似たような性質のものなのですが、queueと異なり先頭と末尾の両方から PushとPopが行えるようになっています。 ちなみにdequeとはDouble Ended Queueのことで、デクまたはディキューと読みます。 次のコードはSTLのdequeをint型で用いた例です。
#include <iostream> #include <deque> using namespace std; int main() { deque<int> dq; deque<int>::size_type i; // 末尾にプッシュ dq.push_back( 4 ); dq.push_back( 3 ); dq.push_back( 2 ); dq.push_back( 1 ); dq.push_back( 0 ); // 先頭にプッシュ dq.push_front( 5 ); dq.push_front( 6 ); dq.push_front( 7 ); dq.push_front( 8 ); dq.push_front( 9 ); // デクのアイテムを列挙 deque<int>::size_type size = dq.size(); for ( i = 0; i < size; i++ ) { cout << (int)dq[i] << ", "; } cout << endl; // 末尾からポップ dq.pop_back(); dq.pop_back(); // 先頭からポップ dq.pop_front(); dq.pop_front(); // デクのアイテムを列挙 size = dq.size(); for ( i = 0; i < size; i++ ) { cout << (int)dq[i] << ", "; } cout << endl; return 0; }#includeusing namespace std; int main() { deque dq; deque ::size_type i; // 末尾にプッシュ dq.push_back( 4 ); dq.push_back( 3 ); dq.push_back( 2 ); dq.push_back( 1 ); dq.push_back( 0 ); // 先頭にプッシュ dq.push_front( 5 ); dq.push_front( 6 ); dq.push_front( 7 ); dq.push_front( 8 ); dq.push_front( 9 ); // デクのアイテムを列挙 deque ::size_type size = dq.size(); for ( i = 0; i < size; i++ ) { cout << (int)dq[i] << ", "; } cout << endl; // 末尾からポップ dq.pop_back(); dq.pop_back(); // 先頭からポップ dq.pop_front(); dq.pop_front(); // デクのアイテムを列挙 size = dq.size(); for ( i = 0; i < size; i++ ) { cout << (int)dq[i] << ", "; } cout << endl; return 0; }]]>
9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, Press any key to continue
vectorは.NET FrameworkでいうArrayListに相当するものと考えられます。 表向きは配列のように振舞いますが、配列とは異なりArrayList同様にそのサイズは可変です。
僕ははじめvectorという名前をみて「ベクトルでも扱うのかな」と思ったのですが、そうではありませんでした。 名前からは数学のベクトルは想像しないほうがいいです。
#include <iostream> #include <vector> using namespace std; // ベクタのアイテムを列挙 template <class _T> void EnumerateVector( vector<_T>& vct ) { for ( vector<_T>::iterator it = vct.begin(); it < vct.end(); it++ ) { cout << *it << ", "; } cout << endl; } int main() { vector<int> vct; vector<int>::size_type i; // ベクタにアイテムをPush for ( i = 0; i < 10; i++ ) { vct.push_back( i ); } EnumerateVector( vct ); // いくつかのアイテムをPop vct.pop_back(); vct.pop_back(); vct.pop_back(); EnumerateVector( vct ); // アイテムの挿入 vct.insert( vct.begin() + 3, 10 ); vct.insert( vct.begin() + 4, 11 ); vct.insert( vct.begin() + 5, 12 ); EnumerateVector( vct ); // アイテムの消去 vct.erase( vct.begin() + 6 ); vct.erase( vct.begin() + 6 ); EnumerateVector( vct ); return 0; }#includeusing namespace std; // ベクタのアイテムを列挙 template void EnumerateVector( vector<_T>& vct ) { for ( vector<_T>::iterator it = vct.begin(); it < vct.end(); it++ ) { cout << *it << ", "; } cout << endl; } int main() { vector vct; vector ::size_type i; // ベクタにアイテムをPush for ( i = 0; i < 10; i++ ) { vct.push_back( i ); } EnumerateVector( vct ); // いくつかのアイテムをPop vct.pop_back(); vct.pop_back(); vct.pop_back(); EnumerateVector( vct ); // アイテムの挿入 vct.insert( vct.begin() + 3, 10 ); vct.insert( vct.begin() + 4, 11 ); vct.insert( vct.begin() + 5, 12 ); EnumerateVector( vct ); // アイテムの消去 vct.erase( vct.begin() + 6 ); vct.erase( vct.begin() + 6 ); EnumerateVector( vct ); return 0; }]]>
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 10, 11, 12, 3, 4, 5, 6, 0, 1, 2, 10, 11, 12, 5, 6, Press any key to continue
EnumerateVectorではイテレータ(反復子)と呼ばれるものを用いてすべてのアイテムを列挙しています。 イテレータの振る舞いは一見ポインタのように見えます。 また、アイテムの追加と削除にもイテレータを用いています。 イテレータは.NET FrameworkのIEnumeratorに相当するものであると言っていいかもしれません。 ただ、このイテレータの使い方に加え、テンプレート関数の使い方が正しい使い方なのかいまいち自信がありません。 STLに関しては今回初めて使ったのでまだまだ勉強不足なのでこの辺で一区切りしておきます。 もし、おかしい部分などあればぜひご指摘ください。