質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

1070閲覧

線形リストで場合分けなしの挿入をダブルポインタで作成する方法がわかりません

apeirogon0813

総合スコア117

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2019/03/20 08:35

編集2019/03/22 06:20

前提・実現したいこと

線形リストの昇順にソートされる挿入関数を以下の図のように作成する上で、関数insert1は
ノードを先頭に挿入するか否かで場合分けをするように作成し、
一方の関数insert2はその場合を分けをなくすためにダブルポインタを用いて作成するのですが、以下の空欄のあ〜きに入る式、特にお〜きがわかりません。
また,それ以前にinsert2のmain関数において
list *head = NULL;
と定義しているのに対し,
insert2の関数の引数ではダブルポインタ
void insert2(list **head_p, ...)
とあるのでmainで定義するのは合致するようにダブルポインタを用いなくていいのでしょうか?

また, mainで引数でinsert(&head,...)とありますが、これはポインタが指しているアドレスではなく、ポインタ自身のアドレスを渡している意味がわかりません。

ググったのですが, ダブルポインタを用いた線形リストの参考になるサイトが見当たらなかったのでよろしくお願いいたします。

![

該当のソースコード

C

1typedef struct list { 2 int data; 3 struct list *next; 4} list 5 6list * list_alloc(int data) { 7 list *p = malloc(sizeof(list)); 8 p->data = data; 9 p->next = NULL; 10 return p; 11} 12 13list * insert1(list *head, int data) { 14 list *new = list_alloc(data); 15 list *p = head; 16 if(||) { //先頭に挿入する条件 17 new->next = p; 18 return new; 19 } else { 20 while(&&) { //挿入箇所を探す 21 p = p->next; 22 } 23 new->next = p->next; 24 p->next = new; 25 return head; 26 } 27} 28 29int main() { 30 list *head = NULL; 31 head = insert1(head,100); 32 head = insert1(head,50); 33 head = insert1(head,20); 34}

C

1void insert2(list ** head_p, int data) { 2 list * new = list_alloc(data); 3 list **p = head_p; 4 while(&&) { 5 p =; //次のnextメンバーを指す 6 } 7 new->next = *p; 8 *p = new; 9} 10int main() { 11 list *head = NULL; 12 insert2(&head,100); 13 insert2(&head,50); 14 insert2(&head,20); 15} 16

イメージ説明

試したこと

まず、"あ"と"い"は先頭が空リストの場合と値が昇順になることを考えて

(p=NULL || data > p->data)
(p=NULL || data < p->data)

次の"う"と"え"は

while(p->next != NULL && data < p->next->data)
while(p->next != NULL && data > p->next->data)

でいいと思うのですが次の"か"と"き"を考える上でinsert2関数内の
list **p = head_p;
とありますが, このhead_pの値はリストの先頭のアドレスを指しているのでしょうか?

**追記: *間接メンバー"->"は選択演算、アドレス演算&より優先順位が高いことを考慮して,
"お"、"か"はそれぞれ
while(*p != NULL && data < (*p)->data)
であり、"き"は
p = &(*p)->next;
であると思うのですが、これは
p = **pと表記することも等しいと思うのですかどうなんでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kasa0

2019/03/20 09:56

"い"と"え"は間違っているよ。
apeirogon0813

2019/03/20 20:40

降順になっているようでした、
guest

回答2

0

まず、"あ"と"い"は先頭が空リストの場合と値が昇順になることを考えて
(p=NULL || data > p->data)
次の"う"と"え"は
while(p->next != NULL && data < p->next->data)

既に指摘があるように、降順になりますね。

でいいと思うのですが次の"か"と"き"を考える上でinsert2関数内の
list **p = head_p;

リストの先頭アドレスですね。

C言語の場合、引数で渡された値を書き換える事ができないので、そのアドレスを渡す事で、(アドレスが指し示す)値を書き換えます。

insert1() と insert2() の違いは、挿入済みリストの戻し方だけかと思います。


insert1() の先頭じゃない場合ですが、挿入位置が違うと思います。
一つ前ではないでしょうか?
また、ソースコードに誤記が多いように感じます。
lost → list, $ → & ではないでしょうか?
list, list_alloc() は、ここでは未定義ですね。

投稿2019/03/20 14:45

pepperleaf

総合スコア6383

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

apeirogon0813

2019/03/22 06:14

申し訳ありません。誤表記は修正いたしました。 なるほど, 上記に追加した画像のような構造になっているのでしょうか? また, 間接メンバー"->"は選択演算*、アドレス演算&より優先順位が高いことを考慮して, "お"、"か"はそれぞれ while(*p != NULL && data < (*p)->data) であり、"き"は p = &(*p)->next; であると思うのですが、これは p = **pと表記することも等しいと思うのですがいかかでしょうか。
guest

0

ベストアンサー

ダミー要素を使わずに先頭要素へのポインタのポインタを使う事で効率化したリストですね。

mainで定義するのは合致するようにダブルポインタを用いなくていいのでしょうか?

やってる事は

c

1void a(int* ip){ *ip = 100; } 2int main(){ 3 int i =0; 4 a(&i); 5 printf("%d\n", i); // => 100が表示される 6}

と同じです。

list *head = NULL;が何を指しているかを書き換えたいのでlist**を引数にとります。

投稿2019/03/20 09:02

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

apeirogon0813

2019/03/22 06:01

なるほど **list = &head と代入している感覚ですかね
asm

2019/03/22 14:58

list *head; list **list = &head; の事ならばそのとおりです。 型名を抜いてしまうと、 list *head; list ****list; **list = &head; の事かと一瞬びっくりしました。
apeirogon0813

2019/03/23 14:18

すみません省略しすぎました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問