元ネタ
Linuxを生み出したリーナス・トーバルズが考える「優れたコード」とは何か?
gigazine.net
とりあえず、すげぇ雑にコード書いてみた。
gccでコンパイル可能( -std=c99 オプション、付けてちょ)。
#include <stdio.h> #include <stdlib.h> #include <string.h> // typedef struct IntListItem { int value; struct IntListItem *next; } IntListItem; // typedef struct { IntListItem *head; } IntList; void remove_01(IntList *l, IntListItem *target) { IntListItem *cur = l->head, *prev = NULL; while(cur != target) { prev = cur; cur = cur->next; } if(prev) { prev->next = cur->next; } else { l->head = cur->next; } } // void remove_02(IntList *l, IntListItem *target) { IntListItem **p = &l->head; while( (*p) != target ) { p = &((*p)->next); // ちょっとだけ括弧を追記 } *p = target->next; } int main() { // IntListItem *wk_before; IntListItem *wk_after; IntList l; l.head = NULL; // 作成 for(int i = 0; i < 5; i++) { wk_after = (IntListItem *)malloc( sizeof(IntListItem) ); wk_after->value = i + 1; wk_after->next = NULL; if (l.head == NULL) { l.head = wk_after; } else { wk_before->next = wk_after; } wk_before = wk_after; } // 表示 IntListItem *wk; IntListItem *del; wk = l.head; while(wk != NULL) { printf("%d \n", wk->value); // 削除用のポインタを取得(後のテスト用) if (wk->value == 5) { del = wk; } wk = wk->next; } printf("\n\n"); // 削除 //remove_01(&l, del); remove_02(&l, del); // 表示 wk = l.head; while(wk != NULL) { printf("%d \n", wk->value); wk = wk->next; } printf("\n\n"); // 削除 //remove_01(&l, l.head); remove_02(&l, l.head); // 表示 wk = l.head; while(wk != NULL) { printf("%d \n", wk->value); wk = wk->next; } return 0; }
「スタンフォード大学の計算機科学講義「Computer Science 101(CS101)」で紹介されていたコード」がremove_01、ライナスさんのコードがremove_02。
とりあえずどっちも動く事を確認。
大学のほうのロジックは普通に理解。
ライナスさんのほう……あぁなるほど「targetにきたら"その次"にすっとばしてtargetを実質的に骨抜きにする」んだ。
あと「先頭の削除」の時は、初っぱなの処理が「List->head へのポインタ」だから、「*p = target->next」でそのまま書き換わるんだ。
うん「言われて見て熟考したらわかる」んだけど、これを「思いつく」のって、すンごいなぁ………
面白くもあり、高みが遠くもあり。