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

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

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

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

Q&A

解決済

1回答

1572閲覧

クイックソート双方向リスト

natsu158

総合スコア1

C

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

0グッド

1クリップ

投稿2020/12/02 13:14

編集2023/12/25 13:41

双方向リストのクイックソートにて
並び替えが以下のように上手くいかないです。

0 1 2 3 3 5 5 6 6 6 6 7 7 7 8 7 7 8 9 10 9

C

1#include<stdio.h> 2#include<stdlib.h> 3 4struct node { 5 int data; 6 struct node *prev; 7 struct node *next; 8}; 9 10 11void print_list(struct node *start); 12void sort_list(struct node **arg_s, struct node **arg_e); 13void swap(struct node **left, struct node **right); 14void trade(struct node **l, struct node **r,struct node **s , struct node **e); 15 16#define MAX 1000 17 18int main(void) { 19 struct node *start, *end, *new,*temp; 20 int i; 21 22 start = end = NULL; 23 for (i = 0; i < MAX * 5; i++) { 24 new = malloc(sizeof(struct node)); 25 if (new == NULL) { 26 fprintf(stderr, "メモリ割り当て失敗\n"); 27 // ここで適切なクリーンアップを行う 28 exit(EXIT_FAILURE); 29 } 30 new->data = rand() % MAX; 31 new->prev = new->next = NULL; 32 33 if (start == NULL) { 34 start = end = new; 35 } else { 36 end->next = new; 37 new->prev = end; 38 end = end->next; 39 } 40 } 41 42 43 printf("ソート前:\n"); 44 print_list(start); 45 46 sort_list(&start, &end); 47 48 printf("ソート後:\n"); 49 print_list(start); 50 51 // メモリの解放処理 52 while (start != NULL) { 53 temp = start; 54 start = start->next; 55 free(temp); 56 } 57 58 return 0; 59} 60 61void print_list(struct node *start) 62{ 63 struct node *p; 64 65 p=start; 66 while(p!=NULL) 67 { 68 printf("%d ",p->data); 69 p=p->next; 70 } 71 printf("\n"); 72} 73 74void sort_list(struct node **arg_s,struct node **arg_e) 75{ 76 struct node *start,*end,*left,*right,*s1,*s2,*e1,*e2; 77 int pivot; 78 79//引数を普通のポインタ型に変える 80 start = *arg_s; 81 end =*arg_e; 82 83 left =start; 84 right =end; 85 86 //基準値を決定する。 87 pivot=left->data; 88 89 while(left!=right&&left->prev!=right) 90 { 91 //pivot以上が出るまで繰り返す。 92 while(left->data < pivot) 93 { 94 left=left->next; 95 } 96 97   //pivot未満が出るまで繰り返す。 98 while(right->data >pivot) 99 { 100 right=right->prev; 101 } 102 103 if(left->prev!=right&&left!=right) 104 { 105 //leftとrightを交換する。 106 trade(&left,&right,&start,&end); 107 //nextを代入する。 108 left=left->next; 109 right=right->prev; 110 } 111 } 112 113 s2=right->next; 114 e1=right; 115 116 s1=start; 117 e1->next=NULL; 118 e2=end; 119 e2->next=NULL; 120 121 122 if(s1!=e1) 123 { 124 sort_list(&s1,&e1); 125 } 126 if(s2!=e2) 127 { 128 sort_list(&s2,&e2); 129 } 130 131 //連結し直す。 132 e1->next=s2; 133 s2->prev=e1; 134 135 //戻り値を設定する 136 *arg_s=s1; 137 *arg_e=e2; 138} 139 140 141//leftとrightを交換する関数。 142void trade(struct node **l, struct node **r,struct node **s , struct node **e) 143{ 144 struct node *start,*end,*left,*right; 145 146 //引数を普通のポインタ型に変える 147 start = *s; 148 end =*e; 149 left =*l; 150 right =*r; 151 152 if(left == start) 153 { 154 start = right; 155 } 156 else 157 { 158 left->prev->next = right; 159 } 160 161 // 後側要素を参照していたprevが、前側の要素を参照するように変更 162 if(right == end) 163 { 164 end = left; 165 } 166 else 167 { 168 right->next->prev = left; 169 } 170 171 // start/endに関係ない部分を交換する 172 left->next->prev = right; 173 swap(&left->next, &right->next); 174 right->prev->next = left; 175 swap(&left->prev, &right->prev); 176 swap(&left, &right); 177 178 *l=left; 179 *r=right; 180 *s=start; 181 *e=end; 182} 183 184// 構造体のポインタ同士を交換する関数 185void swap(struct node **left, struct node **right) 186{ 187 struct node *tmp; 188 189 tmp = *left; 190 *left = *right; 191 *right = tmp; 192} 193

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

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

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

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

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

y_waiwai

2020/12/02 14:19

このままではコードが読みづらいので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
natsu158

2020/12/02 14:40

すみませんでした。
kazuma-s

2020/12/02 15:03

回答するには、情報が不足しています。 struct node の定義がありません。 ex4.h の内容が分かりません。 main がありません。 データの入力がありません。
Zuishin

2020/12/03 00:07

trade をやけにややこしくしていますが、ノードのつなぎ合わせをかえなくても data を取り換えるだけでよくないですか?
natsu158

2020/12/03 02:55

data変えちゃダメだからです。
Zuishin

2020/12/03 03:18

人に聞くのはいいんですか?
guest

回答1

0

ベストアンサー

質問のコードが消されてしまいましたが、trade関数がよくわからなかったのと、
リストのクイックソートに興味がわいたので、全部書き直してみました。

C

1#include <stdio.h> // printf 2#include <stdlib.h> // rand, srand 3#include <time.h> // time 4 5#define MAX 1000 6#define N 20 7 8struct node { int data; struct node *prev, *next; }; 9 10void print_list(struct node *p) 11{ 12 for (; p; p = p->next) printf("%d ", p->data); 13 putchar('\n'); 14} 15 16void print_list_reverse(struct node *p) 17{ 18 while (p->next) p = p->next; 19 do printf("%d ", p->data); while (p = p->prev); 20 putchar('\n'); 21} 22 23struct node *insert(struct node *head, struct node *p) 24{ 25 p->prev = NULL; 26 p->next = head; 27 if (head) head->prev = p; 28 return p; 29} 30 31struct node *sort(struct node *head) 32{ 33 if (!head->next) return head; 34 35 int pivot = head->data; 36 struct node *left = NULL, *right = NULL, *p, *next; 37 38 for (p = head->next; p; p = next) { 39 next = p->next; 40 if (p->data < pivot) 41 left = insert(left, p); // pivot より小さいものは left へ 42 else 43 right = insert(right, p); // pivot 以上のものは right へ 44 } 45 if (left) left = sort(left); // left があれば left をソート 46 if (right) right = sort(right); // right があれば right をソート 47 48 head->next = right; // pivot に right をつなぐ 49 if (right) right->prev = head; // pivot に right をつなぐ 50 if (!left) return head; // left が無ければ、pivot が先頭 51 52 p = left; 53 while (p->next) p = p->next; // left の最後を探す 54 p->next = head; // left に pivot をつなぐ 55 head->prev = p; // left に pivot をつなぐ 56 return left; // left が先頭 57} 58 59int main(void) 60{ 61 srand((unsigned int)time(NULL)); 62 63 struct node *head = NULL, *tail = NULL; 64 for (int i = 0; i < N; i++) { 65 struct node *p = malloc(sizeof(struct node)); 66 p->data = rand() % MAX; 67 p->prev = tail; 68 p->next = NULL; 69 if (tail) tail->next = p; 70 else head = p; 71 tail = p; 72 } 73 print_list(head); 74 head = sort(head); 75 printf("ソート後:\n"); print_list(head); 76 printf("ソート後(逆順):\n"); print_list_reverse(head); 77}

実行結果

text

1614 876 377 404 59 252 277 661 563 169 49 746 384 449 624 344 826 491 173 981 2ソート後: 349 59 169 173 252 277 344 377 384 404 449 491 563 614 624 661 746 826 876 981 4ソート後(逆順): 5981 876 826 746 661 624 614 563 491 449 404 384 377 344 277 252 173 169 59 49

投稿2020/12/03 09:17

編集2020/12/03 12:42
kazuma-s

総合スコア8224

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

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

natsu158

2020/12/03 10:19

わざわざありがとうございます。 参考にしてみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問