リンクとは?
今までの悩み
どれだけメモリが必要になるかを調べてからmallocで確保する必要があった。
事前にメモリ数を調べるのが大変面倒くさい。
もっと一つずつ確保して入れれたら楽だなーー
これを叶えるのがリンク
✔️ 「要素の数が変わる」
✔️ 「途中で消したり入れたりしたい」
✔️ 「サイズが決まってない」
こんな時にはリンクを使った方が簡単。
つまりは今までのmallocのやり方よりも自由度が上がる。
mallocで確保した配列はデータが厳しく整列されられててインデックスで追ってた。
リンクでは、もっと自由度が上がるからバラバラにいてもいい。
その代わり次の人(データ)がわかるように前の人から次の人(データ)がどこにいるかだけは聞きたい。次の人(データ)がどこにいるかっていうのはポインタで簡単に表せるから、リンクではポインターで追える。
その人&次の人の場所を知ってる状態(データとポインタを持ってるハコ)==ノード というらしい。(ざっくり)
RPGで村人に重要人物の場所を聞いて回る感覚。
お前は聞かれたら次の人はこの人の場所を教えろよってデータに教え込むこと == リンクする
ってことみたい。
1、データだけ作る(次のデータのアドレスは持ってない)
#include "libft.h"
#include <stdio.h>
#include <stdlib.h> // ← malloc, free を使うので必要
t_list *ft_lstnew(void *content)
{
t_list *node;
node = (t_list *)malloc(sizeof(t_list));
if (!node)
return (NULL);
node->content = content;
node->next = NULL;
return (node);
}
int main(void)
{
t_list *node;
node = ft_lstnew("42tokyo");
printf("%s\n", (char *)node->content);
free(node);
return (0);
}
2、先頭のデータとしてリストにノードを追加する
変更する時の注意点
node1 のリストにnode2を先頭ノードにしたい場合
そのままnode2 を先頭ノードにした後にリンクしようとしてもnode1がどこにいるかわからなくな る。だから先に、node2に『お前は元々のリストの先頭を教えなよ』ってしておいてから先頭の中身とポインタ(つまりをnode2全体)をnode2にする必要がある。
3、リストのノード数を数える
strlenのwhile(*str)のように〇〇がnullになるまで回そう!としてnextのポインタがnullになるまで回そうと思った。
しかしこれには落とし穴があり、最後のノードが反映されない。
例えばA → B → C → NULLの時、「次の人がいる?」って聞くと、C は「いない!」って答える。
でもcは存在する..となって間違ってしまう。
ではwhile(str)みたいにlstで回す?と思ったがこれも失敗。
typedef struct s_list
{
void *content;
struct s_list *next;
} t_list;
この構造体いただいても何もできない。両方nullになるまで回してもただ中身ないだけ次ないだけで存在はしてるのでまた間違えちゃう。
最後にlst(アドレス)で回す方法。これは正解だけどアドレスが存在=ノード存在と言えるのかで迷ったが上の通り「ただ中身ないだけ次ないだけで存在はしてる」ことになる。住所あるけど家建ててなくて空き地になってるみたいなもの。
次のノードに行くには現在のノード(lst)に次のポインタを入れてあげるだけでok(lst = lst -> next;)
3、リストの最後のノードを返す
今回は逆。例えばA → B → C → NULLの時に、lst(アドレス)で回す(ノードが存在しなくなるまで回す)nullでも存在してるのでnullまで行ってしまう。今回はnextのポインタがnullになるまで回すとcで止まってくれる。
4、リストの最後にノードを追加
3を応用して最後のノードに追加したノードをリンクするだけ。簡単。
5、特定のノードの中身(content)を削除する。
⚠️nextのポインタ(次がどこか教える)機能までは消さない!!
Discussion