• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C言語のリストのソートについて質問します。)

C言語のリストのソートについて質問します

このQ&Aのポイント
  • C言語のリストのソートについて質問します
  • リストのソートアルゴリズムは機能しているが、複数回実行する必要があります。一度で完全にソートする方法を知りたいです。
  • 降順のソートも同様に問題があります。アドバイスをいただけますか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.7

まずリストの操作では中のデータを操作してはいけません。この場合は単純ですが実際には構造が不明な場合が多いのです。ポインタを繋ぎかえるのが基本的です。 バブルソートは極めて簡単で単純に隣同士を入れ替えるだけです。 struct ans root; struct ans *back,*temp,*last; root.next=head; last=NULL; とすると内側のループは以下のように記述できます。(携帯からなのでコンパイルしていません) for(back=&root;(head=(temp=head->next))!=last;back=temp)  if(head->data<temp->data){   temp->next=head->next;   back->next=head;   head->next=temp;  } これを交換する最後のデータがリスト先頭に達するまで繰り返すだけです。 for(last=NULL;(head=root.next)!=last;last=temp) ・・・ return root.next; バブルソートはデータが多いと直ぐ破綻しますが、とりあえず動くようにしてみてください。 動いたらバブルソートの改良、双方向リンク・リストに書き換えみる事です。 バブルソートは昇順に並べる場合には、交換が発生したときに最小値がどうか調べて、最小値を先頭に移動する事で実行時間の短縮ができます。また一度も交換が発生しなければ打ち切ります。 データが数万個以上でも実用的なソートもありますが、それはリンクの操作をマスターしてからですね。

aida13
質問者

お礼

ありがとうございます。やはり双方向リストを使わなければ無理なようですね。勉強して再チャレンジしてみたいと思います。

その他の回答 (8)

回答No.9

#7です。ミスがありました。 for(back=&root;(head=(temp=head->next))!=last;back=temp) はfor(back=&root;(head=(temp=head)->next)!=last;back=temp) です。(-o-;)

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.8

>挿入そのものは 2/n でも、 これを「2ぶんのエヌ」と読ませるのは至難の業です。 どう見ても「エヌぶんの2」としか読めません。

回答No.6

済みません、訂正です。 挿入そのものは 2/n でも、それを n個分繰り返すから、全体のオーダーとしては n^2 ですね。 最近ぼけてます。

回答No.5

挿入時にソートなら、挿入の前後でソートができているというのが仮定できるはずなので(少なくとも、挿入した後はソート済み……だから、ひとつ以上挿入したらその時点ではソート完了)処理オーダーはリストでも n / 2 の気がする。 先頭から確認して、大きい/小さい要素に突き当たったらそこに挿入……でいいのかな?

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.4

>「データを挿入するときにソート」したら n個のデータに対して n^2 時間かかるけど, >「データの挿入だけしておいてあとでソート」したら n log n 時間ですむから速いよね>#1. まあ、5件くらいのデータだからいいじゃないですか。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

「データを挿入するときにソート」したら n個のデータに対して n^2 時間かかるけど, 「データの挿入だけしておいてあとでソート」したら n log n 時間ですむから速いよね>#1. さておき, このプログラムじゃダメダメですよ. sort_up でやってることって, しょせん「バブルソートの 1パス分」だけだもの. 手を動かして紙の上で実際にやってみましたか? あと, sort_up の second_head = (struct ans *)malloc(sizeof(struct ans)); って何の意味があるの? その直後で second_head に代入してるから, これは結局システムを圧迫するためだけだよね? ソートアルゴリズムなんかいっくらでもあるから, そのうち「リストに適切」なものをちゃんと調べて実装すればいいんだけどなぁ.

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.2

>両端にNULLを置いてしまったらsort_up関数内の >   if( head->next == NULL )に引っかかってしまいそうな気もする 何をおっしゃっているのか、さっぱりわかりません。 双方向リストといってもいろんな考え方がありますが、 よくありそうなのは下記のとおりです。どこにも矛盾はないはずです。 先頭データ(仮に左端とします)のnextポインタ:左から2番目のデータを指す 先頭データのprevポインタ:NULL(先頭の左側にはデータがない) 最後尾(右端)データのnextポインタ:NULL(最後尾の右側にはデータがない) 最後尾データのprevポインタ:右から2番目のデータを指す

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.1

そもそも、リスト構造は、構築した「後で」ソートするには あまり向いていないデータ構造です。 データをリストに「挿入する」ときにソートするようにすれば、 すべてのデータを挿入した時点でソート済みのリストができあがっています。 逆順のソートがしたければ、双方向リストを作ればよいでしょう。

aida13
質問者

お礼

なるほど!確かに前のdataも見れるならうまくいきそうです。その場合前を見る(struct ans *prev)とするなら、(struct ans *next)をsort_up関数内で使った式でそのまま流用しても大丈夫でしょうか?

aida13
質問者

補足

考え方はわかりましたが、自分は双方向リストを使ったことがないので何とも…。両端にNULLを置いてしまったらsort_up関数内の      if( head->next == NULL )に引っかかってしまいそうな気もするんですが…

関連するQ&A

専門家に質問してみよう