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

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

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

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

C

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

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

連結リスト

連結リストとは、データ構造のひとつであるリストの中で、要素が前後の要素の情報を持つことで、要素が連結(リンク)しているリストの事を呼びます。

Q&A

解決済

2回答

1548閲覧

クイックソート リスト構造体

cat_is_freedom

総合スコア6

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

C

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

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

連結リスト

連結リストとは、データ構造のひとつであるリストの中で、要素が前後の要素の情報を持つことで、要素が連結(リンク)しているリストの事を呼びます。

0グッド

0クリップ

投稿2021/05/15 02:55

リスト構造体に入力された情報を昇順、降順に並べ替えたいです。

リスト構造体をクイックソートをつかって昇順、降順に並び替えたいです。
クイックソートを使うには基準値を決める必要があると、学んだのですが、リストの数が変化する中で、どう基準値を決め、並び替える方法を知りたいです。
そもそもリスト構造体をクイックソートで並び替えれるのでしょうか?

以下並び替えたいリスト構造体のコードです。

該当のソースコード

#include <stdio.h> #include <string.h> #include <stdlib.h> #define NO_PROBLEM 0 #define ERROR 1 typedef struct student { int id; char name[10 + 1]; struct student *next; } PERSON_t; static PERSON_t *head = NULL; static PERSON_t *tail = NULL; int add_person(int id); int sort_person(void); void get_string(char *str, unsigned int num); int get_person_id(PERSON_t *p); int get_person_name(PERSON_t *p); int main(void) { int number = 0; int id = 0; int ret; int end_flag = 0; while(end_flag == 0) { printf("1追加入力\n2ソート\n0.終了\n "); scanf("%d",&number); fflush(stdin); switch(number){ case 1: id++; ret = add_person(id); if(ret == NO_PROBLEM){ puts("追加完了"); } break; case 2: ret = sort_person(); if(ret == NO_PROBLEM){ puts("並べ替え完了"); } break; default: break; } } return 0; } int sort_person(void){ return 0; } int add_person( int id) { PERSON_t *data; int ret = NO_PROBLEM; data = (PERSON_t *)malloc(sizeof(PERSON_t)); data->id = id; printf("ID→"); printf("%d\n",data->id); get_person_name(data); if (head == NULL) { head = data; tail = data; } else { tail->next = data; tail = data; } tail ->next = NULL; return ret; } void get_string(char *str, unsigned int num) { int i = 0; int c = 0; memset(str, 0, num ); while (strlen(str) < num - 1 ) { c = getchar(); if (c != '\n') { str[i] = c; i++; } else { break; } } } int get_person_name(PERSON_t *p){ int ret = NO_PROBLEM; printf("名前→"); get_string( p->name, sizeof p->name ); return ret; }

補足情報(FW/ツールのバージョンなど)

windows10 Cpad

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

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

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

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

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

cat_is_freedom

2021/05/15 10:48

認識しておりませんでした。 対応いたします。
guest

回答2

0

ベストアンサー

リストのクイックソートやってみました。

C

1#include <stdio.h> // printf, scanf, putchar, puts 2#include <string.h> // strcmp 3#include <stdlib.h> // malloc 4 5#define NO_PROBLEM 0 6 7typedef struct student { 8 int id; 9 char name[10 + 1]; 10 struct student *next; 11} PERSON_t; 12 13static PERSON_t *head = NULL; 14static PERSON_t *tail = NULL; 15 16int add_person(int id); 17int sort_person(void); 18PERSON_t * quick_sort(PERSON_t *a); 19void print_person(PERSON_t *p); 20 21int main(void) 22{ 23 int number = 0; 24 int id = 0; 25 while (1) { 26 printf("1.追加入力 2.ソート 3.表示 0.終了: "); 27 scanf("%d", &number); 28 switch (number) { 29 case 0: 30 return 0; 31 case 1: 32 if (add_person(++id) == NO_PROBLEM) puts("追加完了"); 33 break; 34 case 2: 35 if (sort_person() == NO_PROBLEM) puts("並べ替え完了"); 36 break; 37 case 3: 38 print_person(head); 39 } 40 } 41} 42 43#define add(q) (p = a, a = a->next, p->next = q, q = p) 44 45PERSON_t * quick_sort(PERSON_t *a) 46{ 47 if (a == NULL || a->next == NULL) return a; 48 PERSON_t *pivot = a, *less = NULL, *greater = NULL, *p; 49 a = a->next; 50 pivot->next = NULL; 51 while (a) { 52 int diff = strcmp(a->name, pivot->name); 53 if (diff < 0) add(less); 54 else if (diff > 0) add(greater); 55 else add(pivot); 56 } 57 less = quick_sort(less); 58 greater = quick_sort(greater); 59 if (less == NULL) a = pivot; 60 else { 61 for (a = p = less; p->next; p = p->next) ; 62 p->next = pivot; 63 } 64 for (p = pivot; p->next; p = p->next) ; 65 p->next = greater; 66 return a; 67} 68 69int sort_person(void) 70{ 71 head = quick_sort(head); 72 return NO_PROBLEM; 73} 74 75int add_person(int id) 76{ 77 PERSON_t *data; 78 data = (PERSON_t *)malloc(sizeof(PERSON_t)); 79 data->id = id; 80 printf("ID->%d\n", data->id); 81 scanf("%10s", data->name); 82 data->next = NULL; 83 tail = head ? tail->next = data : (head = data); 84 return NO_PROBLEM; 85} 86 87void print_person(PERSON_t *p) 88{ 89 for (; p; p = p->next) printf(" %s", p->name); 90 putchar('\n'); 91}

実行例

text

11.追加入力 2.ソート 3.表示 0.終了: 1 2ID->1 3ccc 4追加完了 51.追加入力 2.ソート 3.表示 0.終了: 3 6 ccc 71.追加入力 2.ソート 3.表示 0.終了: 1 aaa 8ID->2 9追加完了 101.追加入力 2.ソート 3.表示 0.終了: 3 11 ccc aaa 121.追加入力 2.ソート 3.表示 0.終了: 1 ddd 13ID->3 14追加完了 151.追加入力 2.ソート 3.表示 0.終了: 1 bbb 16ID->4 17追加完了 181.追加入力 2.ソート 3.表示 0.終了: 3 19 ccc aaa ddd bbb 201.追加入力 2.ソート 3.表示 0.終了: 2 21並べ替え完了 221.追加入力 2.ソート 3.表示 0.終了: 3 23 aaa bbb ccc ddd 241.追加入力 2.ソート 3.表示 0.終了: 0

バグがあるかもしれません。どうでしょうか?

追記
コードの説明です。
変数名{変数の値}。値がポインタの時は * で -> の先のオブジェクトを指す。
->{構造体の値} は一つ前の * で指されるオブジェクト。

head{}->{1,"ccc",}->{2,"aaa",}->{3,"ddd",}->{4,"bbb",NULL}
というリストができたとする。

quick_sort に入ると、
a{}->{1,"ccc",}->{2,"aaa",}->{3,"ddd",}->{4,"bbb",NULL}

pivot = a, a = a->next, pivot->next = NULL; を実行すると、
pivot{}->{1,"ccc",NULL}
a{
}->{2,"aaa",}->{3,"ddd",}->{4,"bbb",NULL}

a のリストの先頭から順番に取り外し、
pivot の "ccc" より小さい name のものを less リストに追加し、
pivot の "ccc" より大きい name のものを greater リストに追加する
ということを繰り返す。

int diff = strcmp(a->name, pivot->name); を実行すると、
"aaa" < "ccc" だから diff は負の値で、a の先頭を less に追加する。
add(less) は、 p = a, a = a->next, p->next = less, less = p なので、
p{}->{2,"aaa",NULL}  (less は NULL だったので)
a{
}->{3,"ddd",}->{4,"bbb",NULL}
less{
}->{2,"aaa",NULL}

int diff = strcmp(a->name, pivot->name); を実行すると、
"ddd" > "ccc" だから diff は正の値で、a の先頭を greater に追加する。
add(greater) は、 p = a, a = a->next, p->next = greater, greater = p なので、
p{}->{3,"ddd",NULL}  (greater は NULL だったので)
a{
}->{4,"bbb",NULL}
greater{*}->{3,"ddd",NULL}

int diff = strcmp(a->name, pivot->name); を実行すると、
"bbb" < "ccc" だから diff は負の値で、a の先頭を less に追加する。
add(less) は、 p = a, a = a->next, p->next = less, less = p なので、
p{}->{4,"bbb",}->{2,"aaa",NULL}  (less の先頭に追加)
a{NULL}
less{}->{4,"bbb",}->{2,"aaa",NULL}

a が NULL なので、while (a) のループを終了

less = quick_sort(less) で less をソート
less{}->{2,"aaa",}->{4,"bbb",NULL}

greater = quick_sort(greater) で greater をソート
greater{*}->{3,"ddd",NULL}

less が NULL なら、a は pivot + greater となるが、
less が NULL でないので、a = less とし、
less と pivot と greater を結合して a を作る。
for (p = less; p->next; p = p->next) ; で、
p が less の最後の要素を指すようにする。
p->next = pivot で less の最後に pivot を連結する。
for (p = pivot; p->next; p = p->next) ; で、
p が pivot の最後の要素を指すようにする。
p->next = greater で pivot の最後に greater を連結する。

return a; でソートと連結が完了したリストを返す。

投稿2021/05/15 10:22

編集2021/05/17 10:24
kazuma-s

総合スコア8224

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

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

cat_is_freedom

2021/05/15 11:37

解答ありがとうございます! 触ってみたところきちんと動きました。 しかし、初心者の私には、コードが省略?して書かれているところが多くあり、理解しきれないところがありました… あとは、リストがないときに何か表示させる必要があるのかな、と思いました。 参考にさせていただきます。
actorbug

2021/05/16 01:22

Prolog の差分リストを応用すれば、最後にリストをたどらなくてよくなりますね。 #define add(q) (*q = a, q = &a->next, a = a->next) PERSON_t* quick_sort(PERSON_t* a, PERSON_t* last) { if (a == NULL) return last; PERSON_t *pivot = a, *less, *greater; PERSON_t **pivot_last = &a->next, **less_last = &less, **greater_last = &greater; a = a->next; while (a) { int diff = strcmp(a->name, pivot->name); if (diff < 0) add(less_last); else if (diff > 0) add(greater_last); else add(pivot_last); } *less_last = *greater_last = NULL; *pivot_last = quick_sort(greater, last); return quick_sort(less, pivot); } int sort_person(void) { head = quick_sort(head, NULL); return NO_PROBLEM; }
cat_is_freedom

2021/05/16 07:37

解答ありがとうございます! ポインタのポインタが出てきて頭が整理する必要があり、自分の力のなさを感じます。。。 とても見やすいコードなので、参考にさせてください。
cat_is_freedom

2021/05/16 07:47

また質問になるのですが、 tail = head ? tail->next = data : (head = data); を違う形に書き直すとどうなりますでしょうか? 調べたところ、「真の時は前式を、偽の時は後式を代入」 と書いてありましたが、if文で書き直せるのでしょうか?
kazuma-s

2021/05/16 09:14

if (head != NULL) . tail = tail->next = data; else . tail = head = data; 質問の次のコードと同じです。 if (head == NULL) { . head = data; . tail = data; } else { . tail->next = data; . tail = data; }
cat_is_freedom

2021/05/17 02:06

もし可能でしたら、コードに解説など入れていただけないでしょうか? プログラムはきちんと動くのですが、なかなか理解しきれません。。。 お時間がありましたら、よろしくお願いいたします。
cat_is_freedom

2021/05/19 15:05

丁寧に解説までしてくださりありがとうございました。
guest

0

そもそもリスト構造体をクイックソートで並び替えれるのでしょうか?

やれなくはないがリストにクイックソートは向いてない。

クイックソートは集合の要素を飛び飛び(ランダム)にアクセスします。
リストは次の要素/前の要素を順にアクセスできますが、
n番目の要素はアタマから次の要素をn回辿らにゃなりませんから。

リストを対象とした速いソートというと...マージソートあたりですかね。

投稿2021/05/15 03:08

episteme

総合スコア16614

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問