| No.001-01 拡張リスト・クラスのテンプレート | 
C++でリスト構造をいちいち作んのめんどくさい
かといってSTLの<vector>やら<list>もなんか今ひとつ使いづらい
   ・・・ので簡単リスト化テンプレートで作ってみました。そして公開。
| 使い方はシンプル | |
| XLIST<クラス名> 変数名; | ・・・宣言 | 
| push(値); | ・・・アイテムをリストに追加 | 
| pop(n); | ・・・n番目のアイテムをリストから削除 | 
| 変数名[n]; | ・・・配列的にアクセス | 
| size(); | ・・・現在のアイテム数の取得 | 
例えば
| #include "xlist.h"; int main(){ XLIST<int> num; // 宣言 num.push(20); // リストに20という値を追加 num.push(21); // リストに21という値を追加 num.push(22); // リストに22という値を追加 num.pop(); // リストから末尾のアイテム(22の値)を削除 printf("%d\n", num[1]); // 画面にリストの2番目の値を出力 return 0; }; | 
というコードを書けば画面(MS-DOSプロンプト)には"21"が表示されます
| xlist.h | 
| #ifndef _XLIST_H_
#define _XLIST_H_
#include <stdio>
#include <stdlib>
//==========================================
//              リスト型テンプレート                            
//==========================================
// 連結アイテム・クラス
template <class T> class LIST_ITEM{
        public:
        T t;                                    // ←アイテム本体   
        LIST_ITEM *next, *before;                       // ノード
        LIST_ITEM(){ next=before=NULL; }        // コンストラクタ
};
//==========================================
//              XLIST   拡張リスト                                      
//==========================================
template <class T> class XLIST {
        private:
        // メンバ変数
        LIST_ITEM<T> *head, *tail;
        LIST_ITEM<T>    *last_use;
        int                             last_use_id;
        int item_length;
        public :
        XLIST();                // コンストラクタ
        ~XLIST();               // デストラクタ
        push(T t);              // アイテム追加
        push(T t, int n);               // アイテム追加
        pop(int n=-1);  // 第n番目のアイテム削除
        val_pop(T t);   // tの値と同じアイテムの削除
        // ランダムアクセス
        LIST_ITEM<T>*   get_ptr_abs(int n);
        LIST_ITEM<T>*   get_ptr_rel(LIST_ITEM<T>* pitem, int n);
        virtual LIST_ITEM<T>*   get_ptr(int n);
        T &operator [](int n);
        T &last();
        del_all();
        init();
        set_default(T &t);
        size();         // アイテム数を返す
        resize(int n);
        swap(int n1, int n2){
                LIST_ITEM<T> *p
                T tmp_t=*get_ptr(n1);
                *get_ptr(n1)=*get_ptr(n2);
                *get_ptr(n2)=tmp_t;
                return 0;
        };
        roll(int n1, int n2);
};
// コンストラクタ 
template <class T> XLIST<T>::XLIST(){ init(); }
// デストラクタ
template <class T> XLIST<T>::~XLIST(){ del_all(); delete head; }
// 初期化               
template <class T> XLIST<T>::init(){
        head = new LIST_ITEM<T>;
        last_use        = tail = head;
        last_use_id     = item_length= 0;
        return 0;
}
// アイテム数           
template <class T> XLIST<T>::size(){
        return item_length;
}
// アイテム数変更               
template <class T> XLIST<T>::resize(int n){
        if (n<0) n=0;
        int i, add_size = n - item_length;
        if (!add_size){
                return item_length;
        }
        else if (add_size>0){
                T t;
                for(i=0;i<add_size;i++) push(t);
                return add_size;
        }
        else if (add_size<0){
                add_size=-add_size;
                for(i=0;i<add_size;i++) pop();
                return -add_size;
        }
        return item_length;
}
// アクセスエラー時の返り値 設定                
template <class T> XLIST<T>::set_default(T &t){ head->t = t; return 0; }
// 全破棄               
template <class T> XLIST<T>::del_all(){
        int i, del_len=size()+1;
        for(i=0;i<del_len;i++) pop();
        return 0;
}
// ====== ランダムアクセス =====================================================
// 演算子 []    
template <class T> T& XLIST<T>::operator [](int n){
        LIST_ITEM<T> *p=get_ptr(n);
        return p->t;
}
// 演算子 []    
template <class T> T& XLIST<T>::last(){
        return tail->t;
}
// 相対パスから    
template <class T> LIST_ITEM<T>* XLIST<T>::get_ptr_rel(LIST_ITEM<T>* pitem, int n){
        if (n>0){
                for(int i=0;i<n;i++) if (pitem->next)   pitem=pitem->next;
        } else if (n<0){
                n=-n;
                for(int i=0;i<n;i++) if (pitem->before) pitem=pitem->before;
        }
//      printf("rel  ");
        return pitem;
};
// 絶対パスから    
template <class T> LIST_ITEM<T>* XLIST<T>::get_ptr_abs(int n){
        LIST_ITEM<T> *pitem=head->next;
        for(int i=0;i<n;i++) if (pitem->next)   pitem=pitem->next;
        return pitem;
}
// ランダムアクセス総括関数    
template <class T> LIST_ITEM<T>* XLIST<T>::get_ptr(int n){
        LIST_ITEM<T> *pitem;
        int i = n-last_use_id, len=size();
        if (n>=len || n<0) return head;
        if (n > abs(i)){
                if ((len-n-1) > abs(i)) pitem = get_ptr_rel(last_use, i);
                else                                    pitem = get_ptr_rel(tail, n-len+1);
        }
        else pitem = get_ptr_abs(n);    // 先頭からノード検索
        if (pitem) {    // 最後にアクセスしたアイテム更新
                last_use        =pitem;
                last_use_id     =n;
        }
        return pitem;
}
// アイテム移動    (第n1番目のアイテムを第n2番目に移動)   
template <class T> XLIST<T>::roll(int n1, int n2){
        if (item_length<=0) return 0;           // LISTアイテムなし
        LIST_ITEM<T> *bef, *nex, *org, *dst;
        if (n1<0 || n1>=item_length) org=tail;  // n1 が範囲外なら末尾を削除
        else org = get_ptr(n1);
        if (n2<0 || n2>=item_length) dst=tail;  // n2 が範囲外なら末尾を削除
        else dst = get_ptr(n2);
        if (!org || !dst || org==head || dst==head || org==dst) return 0;
        // ターゲット・アイテムを一時リストからはずす
        bef=org->before;
        nex=org->next;
        if (bef) bef->next=nex;
        if (nex) nex->before=bef;
        // 一時リストからはずしていたターゲット・アイテムを目的位置にセット
        bef=dst->before;        bef->next=org;  // ■-□-□             ■の設定
        dst->before=org;                                        // □-□-■             ■の設定
        org->next=dst;          // □-■-□             ■の設定
        org->before=bef;        // □-■-□             ■の設定
        tail = last_use =get_ptr_abs(item_length);
                last_use_id     =item_length-1;
        return item_length;
}
// アイテム追加   
template <class T> XLIST<T>::push(T t){
        LIST_ITEM<T> *old_tail=tail;            // 更新前の末尾ポインタ保持
        tail->next = new LIST_ITEM<T>;          // 末尾アイテムのnextに新リスト作成
        tail=tail->next;                                // 新リストにtailポインタを合わせる
        tail->t = t;                                    // 新リストにアイテム代入
        tail->before=old_tail;
        item_length++;
        return item_length;
};
// アイテム追加 (挿入型)  
template <class T> XLIST<T>::push(T t, int n){
        if (n>=item_length) return push(t);
        if (n<=0) n=0;
        LIST_ITEM<T> *bef_pitem, *nex_pitem, *pitem;
        bef_pitem=get_ptr(n-1);                 // 挿入先の前ポインタ取得(確実に存在)
        nex_pitem=bef_pitem->next;              // 挿入先の次ポインタ保持(NULLのときもあり)
        pitem = new LIST_ITEM<T>;       // 末尾アイテムのnextに新リスト作成
        pitem->t = t;                                   // 新リストにアイテム代入
        pitem->before=bef_pitem;
        pitem->next=nex_pitem;
        bef_pitem->next = pitem;
        if (nex_pitem) nex_pitem->before = pitem;
                item_length++;
                last_use        =pitem;
                last_use_id     =n;
        return item_length;
};
// アイテム削除    (第n番目のアイテム削除)   
template <class T> XLIST<T>::pop(int n){
        if (item_length<=0) return 0;           // LISTアイテムなし
        LIST_ITEM<T> *del, *bef, *nex;
        if (n<0 || n>=item_length) del=tail;    // n が範囲外なら末尾を削除
        else del = get_ptr(n);
        if (del==head) return 0;
        bef = del->before;      // 削除アイテムの前のノードGET
        nex = del->next;        // 削除アイテムの次のノードGET
        bef->next=nex;          // 前のノードは確実に存在するのでじかに更新
        if (nex) {
                nex->before=bef;        // 削除アイテムが末尾なときnexはNULLなので回避
        }
        else tail=bef;
        delete del;
        item_length--;
                last_use        =bef;   // 最後にアクセスしたアイテム更新(前のノードに代入)
                last_use_id     =n-1;
        return item_length;
}
// tの値と同じアイテムの削除
template <class T> XLIST<T>::val_pop(T t){
        LIST_ITEM<T> *p;
        for(int i=0;i<item_length;i++){
                p=get_ptr(i);
                if (p->t==t) {
                        pop(i);
                        return 1;
                }
        }
        return 0;
};
#endif  // _XLIST_H_
          | 
| ●XLIST サンプル | 
| #include "xlist.h"
int main(){
    XLIST<int> list;    // int型のリストを宣言
    list.push(20);      // アイテムを追加
    list.push(21);
    list.push(22);
    list.push(23);
    list.push(24);
    list.push(25);
    list.pop(3);        // list[3]をリストから削除
    for(int i=0;i<list.size();i++){
        printf("list[%d]=%d\n", i, list[i]);    // list[i]を表示
    }
    printf("list.size(); %d\n", list.size());   // リストアイテム数を表示
    list.del_all();                             // アイテムの全削除、ただしメモリは解放しない。
    printf("list.del_all();呼び出し \n");
    printf("list.size(); %d\n", list.size());   // リストアイテム数を表示
    list.resize(4);                             // アイテムの数を4個にする
    printf("list.size(); %d\n", list.size());   // リストアイテム数を表示
    return 0;
} | 
| 実行結果  | 
上記ソースは全て自由に改編して使ってかまいませんが必ず自己責任でね。
| - | ホームへ | →次へ 001-02 |