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

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

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

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

Q&A

解決済

2回答

2395閲覧

リスト構造を用いた挿入ソート

slushii

総合スコア19

C

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

0グッド

0クリップ

投稿2019/04/24 02:54

不明点

c言語でリスト構造を用いた挿入ソートを作っています。
sort関数内に誤りがあり、segmentation faultを返してしまいます。
誤りを指摘していただければと思います。
よろしくお願い致します。

c

1#include <stdio.h> 2#include <stdlib.h> 3 4typedef struct _cell { 5 int element; 6 struct _cell *next; 7}cell; 8 9typedef struct _list{ 10 cell *head; 11}list; 12 13list* create() { 14 list *L = (list *)malloc(sizeof(list)); 15 L->head = (cell *)malloc(sizeof(cell)); 16 L->head->next = NULL; 17 L->head->element = -1; 18 return L; 19} 20 21void addFirst(list *L, int element) { 22 cell *add = (cell *)malloc(sizeof(cell)); 23 add->element = element; 24 add->next = L->head->next; 25 L->head->next = add; 26} 27 28 29 30void print(list *L) { 31 cell *ptr = L->head->next; 32 while(ptr != NULL) { 33 printf("%d ", ptr->element); 34 ptr = ptr->next; 35 } 36 printf("\n"); 37} 38 39void sort(list *L) { 40 cell *ptr = L->head->next->next; 41 cell *prev = L->head->next; 42 while(ptr != NULL){ 43 while(prev->element > ptr->element) { 44 prev->next = prev; 45 prev = ptr; 46 } 47 ptr = ptr->next; 48 } 49 printf("%d ", ptr->element); 50} 51 52int main() { 53 list *L = create(); 54 55 addFirst(L, 5); 56 addFirst(L, 3); 57 addFirst(L, 5); 58 addFirst(L, 6); 59 print(L); 60 sort(L); 61 62 return 0; 63}

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

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

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

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

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

guest

回答2

0

ベストアンサー

Segmentation fault になる直接の原因はNULLアクセスだと思われます。
sort()の最後のprintf で ptr->element にアクセスしていますが ptr は while (ptr != NULL) を抜けた後なので NULL です。
このprintfの位置(タイミング)を見直せばそのエラーは解消できます。
しかしそもそもソート処理自体も正しく無さそうですよ。

投稿2019/04/24 03:22

HiroshiWatanabe

総合スコア2160

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

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

slushii

2019/04/26 05:06 編集

もし良ければSORT処理の誤りも教えて頂けませんでしょうか?
HiroshiWatanabe

2019/04/26 07:24

prev->next = prev; で prev の次が自分自身を指すようになってしまっていませんか?その後に prev = ptr; としているので次の while 時には prev->element > ptr->element は同じ物同士で比較しているので必ずfalseになりループ1回で抜けます。なのでそこで無限ループに陥るというトラブルには見舞われませんが、逆に言えばwhileループである意味も無いという理屈にならないでしょうか?これならwhileではなくifで良いという事になりますが恐らく繰り返したいのだろうと推察するとこの中で行うべき処理が足りないという想像に至ります。自分が想定しているアルゴリズム通りの処理になっているかを落ち着いて見直してみてください。
slushii

2019/04/28 10:59

ひどいコードですみませんでした。ご丁寧にありがとうございました。
guest

0

連結リストのソートは難しいと言うか結構やっかいですね。
私もかなり探したのですが、配列を対象にしたソートのサンプルプログラムでしたらいくらでも見つかりますが、連結リストのサンプルプログラムはあまりありませんでした。

ソートの方法は配列の場合と同じようにいろいろありますが、(配列の場合と同じやり方の)挿入ソートで単方向リストをソートしようとすると結構大変です。

発想を変えて(と言うと大げさですが)新たにリストを作っていくのが実装としては楽ではないかと思います。幸いに連結リストはリンクの付け替え(張り替え)は自由に(しかも低コストで)できますので、元のリストからノードを切り離し新規リストに昇順(或いは降順)を保つように追加していればいいです。

別の方法として、元のリストから最大の(或いは最小の)ノードを選んで、新規リストの先頭に追加していくというやり方もあります。こっちの方がちょっと速いみたいです。

なお、連結リストのソートはマージソートが比較的速いようです。

投稿2019/04/26 11:37

Bull

総合スコア986

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問