No.001-まとめ 拡張リスト・クラスのテンプレート(総合) |
| 長所 | 短所 | |
| XLIST | ・シンプルにリスト化 ・定数をそのままリスト化できる |
・強制的にデストラクタが発生する。 ・高速push、popは無理 |
| PLIST | ・デストラクタの発生が制限できる。 ・ポインタ管理なのでXLISTより速い。 |
・定数をナマでリスト化はできない。必ずポインタ使用。 ・高速push、popは無理 |
| QLIST | ・メモリの再利用により高速push、popが可能。 | ・メモリをどこで解放するかがユーザの負担になる。 |
| 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番目のアイテム削除
// ランダムアクセス
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; // n が範囲外なら末尾を削除
else org = get_ptr(n1);
if (n2<0 || n2>=item_length) dst=tail; // n が範囲外なら末尾を削除
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;
}
// アイテム削除 (第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;
}
// アイテム追加
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;
};
#endif // _XLIST_H_
|
| plist.h |
#ifndef _PLIST_H_
#define _PLIST_H_
#include <stdio.h>
#include <stdlib.h>
#include "xlist.h"
//==========================================
// PLIST ポインタ・リスト
//==========================================
template <class T> class PLIST {
char destruct_flag;
XLIST<T*> xlist; // has a型(多態push作成のためis aでない)
public :
// n1番目とn2番目のアイテムを交換する(swap)
swap(int n1, int n2){
T* tmp_t=xlist[n1];
xlist[n1]=xlist[n2];
xlist[n2]=tmp_t;
};
// 最後のアイテム(参照)を返す
T* &last(){ return xlist.last(); };
// アイテム数を返す(len, size で同じもの)
len(){ return xlist.size(); };
size(){ return xlist.size(); };
// リサイズ
resize(int n){
int old_size=size(); // 旧サイズの保持
int res=xlist.resize(n); // メンバxlistでリサイズ実行
int i;
if (old_size<size()){
for(i=old_size;i<size();i++) xlist[i]=a_push(); // 追加した分だけメモリ確保
}
return res;
};
// pop時アイテムのdeleteしないよう設定する
set_no_destruct(){ return destruct_flag=0; }
// コンストラクタ
PLIST(){
destruct_flag=1; // pop時アイテムのdelete(アイテムのデストラクタが走る)
T *t=NULL; // デフォルト値はNULL
xlist.set_default(t); // デフォルト値はNULLであることをxlistに設定
};
// デストラクタ
~PLIST(){ del_all(); };
// オート・プッシュ
T *a_push(int n=-1){
T* pt = new T;
if (n==-1) xlist.push(pt); // n==-1ならアイテムは末尾に追加
else xlist.push(pt, n); // n が範囲内ならアイテムはn番目に挿入
// 返り値
return (n==-1)? last() : xlist[n];
}
// アイテム追加(通常プッシュ)
// 引数 t : 値、 n : 挿入位置
T *push(T &t, int n=-1){
T* pt = new T;
*pt=t;
if (n==-1) xlist.push(pt); // n==-1ならアイテムは末尾に追加
else xlist.push(pt, n); // n が範囲内ならアイテムはn番目に挿入
// 返り値
return (n==-1)? last() : xlist[n];
}
// ポインタ引数でアイテム追加
// 引数 t : 値、 n : 挿入位置
p_push(T *t=NULL, int n=-1){
if (!t) t = new T;
if (n==-1) xlist.push(t);
else xlist.push(t, n);
return 0;
};
// 第n番目のアイテム削除
pop(int n=-1){
if (destruct_flag) delete xlist[n];
xlist[n]=NULL;
xlist.pop(n);
return 0;
};
// tの値と同じアイテムの削除
val_pop(T *t){ return xlist.val_pop(t); }
// ランダムアクセス
T* &operator [](int n){ return xlist[n]; };
// 第n1番目のアイテムを第n2番目に移動
roll(int n1, int n2){ return xlist.roll(n1, n2); }
// 全アイテム削除
del_all(){
int i, del_len=xlist.size();
for(i=del_len-1;i>=0;i--) pop(i);
return 0;
}
};
#endif // _PLIST_H_
|
| qlist.h |
#ifndef _QLIST_H_
#define _QLIST_H_
#include <stdio>
#include <stdlib>
#include "plist.h"
//==========================================
// QLIST クイック・リスト
//==========================================
template <class T> class QLIST {
public :
int pret_size;
PLIST<T> plist; // has a型(多態push作成のためis aでない)
swap(int n1, int n2){
plist.swap(n1, n2);
};
T* &last(){ return plist.last(); };
size() { return pret_size; }; // アイテム数を返す
mem_size() { return plist.size(); }; // メモリ・アイテム数を返す
resize(int n){
if (n>plist.size()) plist.resize(n); // 追加
return pret_size=n;
};
mem_resize(int n){ return plist.resize(n); };
T *a_push(int n=-1){ // オート・プッシュ
if (n<0 || n>pret_size) n=pret_size;
if (pret_size>=plist.size()) plist.a_push(n);
else if (n>=0 && n<pret_size) {
plist.roll(pret_size, n);
// *(plist[n])=t; // 通常プッシュ
}
pret_size++;
return plist[n];
}
pop(int n=-1){
if (pret_size<=0) return 0;
if (n>0) plist.roll(n, pret_size);
pret_size--;
}
mem_pop(int n=-1){ return plist.pop(n); }
// ランダムアクセス
T* &operator [](int n){
if (pret_size<=n) return plist[-1];
return plist[n];
};
// コンストラクタ
QLIST(){
pret_size=0;
};
del_all(){
pret_size=0;
}
mem_del_all(){
pret_size=0;
plist.del_all();
}
};
#endif // _QLIST_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;
} |
| ●PLIST サンプル | 実行結果![]() |
#include "plist.h"
int main(){
PLIST<int> list; // int型のポインタ・リストを宣言
int n=100, *pn;
pn=list.a_push(); // アイテムを追加しそのアイテムへのポインタを得る
*pn=n++; // 追加したアイテムに値を代入
pn=list.a_push();*pn=n++;
pn=list.a_push();*pn=n++;
pn=list.a_push();*pn=n++;
pn=list.a_push();*pn=n++;
pn=list.a_push();*pn=n++;
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;
} |
| ●QLIST サンプル | 実行結果![]() |
#include "qlist.h"
int main(){
QLIST<int> list; // int型のクイック・リストを宣言
int n=100, *pn;
pn=list.a_push(); // アイテムを追加しそのアイテムへのポインタを得る
*pn=n++; // 追加したアイテムに値を代入
pn=list.a_push();*pn=n++;
pn=list.a_push();*pn=n++;
pn=list.a_push();*pn=n++;
pn=list.a_push();*pn=n++;
pn=list.a_push();*pn=n++;
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()); // リストアイテム数を表示
printf("list.mem_size(); %d\n", list.mem_size()); // リストアイテムの現在のメモリ確保数を表示
list.mem_del_all();
printf("list.mem_del_all();呼び出し \n");
printf("list.mem_size(); %d\n", list.mem_size()); // アイテムの全削除、アイテム用メモリも解放。
list.resize(4); // アイテムの数を4個にする
return 0;
}
|
上記ソースは全て自由に改編して使ってかまいませんが必ず自己責任でね。