双方向リスト[Doubly Linked List]は、エレメントの次エレメントだけでなく前エレメントのポインタを持った構造で、前後に自由に移動することが出来ます。

双方向リスト[Doubly Linked List]は、エレメントの次エレメントだけでなく前エレメントのポインタを持った構造で、前後に自由に移動することが出来ます。
LIST構造を使用するには、まずLIST形式のデータ構造を定義必要があります。
LIST_ENTRYはLIST形式のデータ構造を定義します。各エレメントに数字が1つだけ入っているLIST構造、Listsを定義してみると、下記のようになります。
struct Lists { LIST_ENTRY(Lists) list_ptr; int32_t data; };
これは、次のように展開されます。
struct Lists { struct { struct Lists *le_next; struct Lists **le_prev; } list_ptr; int32_t data; };
これは定義だけで、まだ実体は無いことに注意してください。
LIST_HEADは、エレメントの先頭アドレスが入る構造体を定義します。
LIST_HEAD(ListsHead, Lists);
これは、次のように展開されます。
struct ListsHead { struct Lists *lh_first; };
これも定義だけで、まだ実体は無いことに注意してください。
LIST_HEAD_INITIALIZERは、LIST_HEADを初期化します。次のように使用します。
// LISTヘッダの実体を定義
struct ListsHead lists_head = LIST_HEAD_INITIALIZER(&lists_head);
LIST_INITは、LISTを初期化します。次のように使用します。
if(!(LIST_EMPTY(&lists_head))) // LISTが空であるかチェック LIST_INIT(&lists_head); // LISTの初期化
LIST_FIRSTは、LISTの先頭エレメントのポインタを返します。
arithmetic = LIST_FIRST(&lists_head);
LIST_ENDは、NULLを返します。
LIST_EMPTYは、LISTが空であるか調べます。
LIST_NEXTは、エレメント(elm)に連結されている次エレメントのポインタを返します。
arithmetic_next = LIST_NEXT(arithmetic,list_ptr);
LIST_INSERT_HEADは、新しいエレメント(elm)をLIST(head)に追加します。
// データ作成 for(i=0;i<5;i++){ number[i].data = i; number[i].list_ptr.le_next = NULL; number[i].list_ptr.le_prev = NULL; } for(i=1;i<=2;i++){ // LISTにデータをセット LIST_INSERT_HEAD(&lists_head, &number[i], list_ptr); }
この結果は、次のようになります。
LIST_INSERT_AFTERは、指定されたエレメント(listelm)の後に、新しいエレメント(elm)を追加します。
arithmetic = LIST_FIRST(&lists_head); // 最初のエレメント(data=2) arithmetic_next = LIST_NEXT(arithmetic,list_ptr); // 指定エレメントの次エレメント(data=1) LIST_INSERT_AFTER(arithmetic_next,&number[0],list_ptr); // data=1)の後ろに(data=0)を挿入
この結果は、arithmetic_next(data=1)の後ろにエレメントnumber[0](data=0)が挿入されます。
LIST_INSERT_BEFOREは、指定されたエレメント(listelm)の前に、新しいエレメント(elm)を追加します。
LIST_INSERT_BEFORE(arithmetic,&number[4],list_ptr); // (data=2)の前に(data=4)を挿入
この結果は、arithmetic(data=2)の前にエレメントnumber[4](data=4)が挿入されます。
LIST_REPLACEは、elmのエレメントをLISTから切り放し、切り放した所にelm2を挿入します。
LIST_REPLACE(&number[4],&number[3],list_ptr); // (data=4)を(data=3)に置換える
結果は、data=4のエレメントが切り放され、data=3のエレメントが挿入されます。
LIST_FOREACHは、headに格納されたエレメントを最初から終りまでループして、varにポインタを返します。
// エレメントの最初から終わりまでループ
LIST_FOREACH(arithmetic, &lists_head, list_ptr){
printf("%d\n",arithmetic->data);
}
結果は、下記のようになります。
3 2 1 0
LIST_REMOVEは、指定されたエレメント(elm)をLIST(head)から削除します。
while((arithmetic = LIST_FIRST(&lists_head)))
LIST_REMOVE(arithmetic,list_ptr); // 指定したエレメントを削除
LISTデータの操作sampleです。