東方算程譚

Oriental Code Talk ── επιστημηが与太をこく、弾幕とは無縁のシロモノ。

目次

Blog 利用状況

ニュース

著作とお薦めの品々は

著作とお薦めの品々は
東方熱帯林へ。

あわせて読みたい

わんくま

  1. 東京勉強会#2
    C++/CLI カクテル・レシピ
  2. 東京勉強会#3
    template vs. generics
  3. 大阪勉強会#6
    C++むかしばなし
  4. 東京勉強会#7
    C++むかしばなし
  5. 東京勉強会#8
    STL/CLRによるGeneric Programming
  6. TechEd 2007 @YOKOHAMA
    C++・C++/CLI・C# 適材適所
  7. 東京勉強会#14
    Making of BOF
  8. 東京勉強会#15
    状態遷移
  9. 名古屋勉強会#2
    WinUnit - お気楽お手軽UnitTest

CodeZine

  1. Cで実現する「ぷちオブジェクト指向」
  2. CUnitによるテスト駆動開発
  3. SQLiteで組み込みDB体験(2007年版)
  4. C++/CLIによるCライブラリの.NET化
  5. C# 1.1からC# 3.0まで~言語仕様の進化
  6. BoostでC++0xのライブラリ「TR1」を先取りしよう (1)
  7. BoostでC++0xのライブラリ「TR1」を先取りしよう (2)
  8. BoostでC++0xのライブラリ「TR1」を先取りしよう (3)
  9. BoostでC++0xのライブラリ「TR1」を先取りしよう (4)
  10. BoostでC++0xのライブラリ「TR1」を先取りしよう (5)
  11. C/C++に対応した、もうひとつのUnitTestFramework ─ WinUnit
  12. SQLiteで"おこづかいちょう"
  13. STL/CLRツアーガイド
  14. マージ・ソート : 巨大データのソート法
  15. ヒープソートのアルゴリズム
  16. C++0xの新機能「ラムダ式」を次期Visual Studioでいち早く試す
  17. .NETでマンデルブロ集合を描く
  18. .NETでマンデルブロ集合を描く(後日談)
  19. C++/CLI : とある文字列の相互変換(コンバージョン)
  20. インテルTBBによる選択ソートの高速化
  21. インテルTBB3.0 によるパイプライン処理
  22. Visual C++ 2010に追加されたSTLアルゴリズム
  23. Visual C++ 2010に追加されたSTLコンテナ「forward_list」
  24. shared_ptrによるObserverパターンの実装
  25. .NETでマンデルブロ集合を描く(番外編) ── OpenCLで超並列コンピューティング
  26. StateパターンでCSVを読む
  27. 状態遷移表からStateパターンを自動生成する
  28. 「ソートも、サーチも、あるんだよ」~標準C++ライブラリにみるアルゴリズムの面白さ
  29. インテルTBBの同期メカニズム
  30. なぜsetを使っちゃいけないの?
  31. WPFアプリケーションで腕試し ~C++でもWPFアプリを
  32. C++11 : スレッド・ライブラリひとめぐり
  33. Google製のC++ Unit Test Framework「Google Test」を使ってみる
  34. メールでデータベースを更新するココロミ
  35. Visitorパターンで遊んでみたよ
  36. Collection 2題:「WPFにバインドできる辞書」と「重複を許す検索set」
  37. Visual C++ 2012:stateless-lambdaとSQLiteのぷち拡張
  38. 「Visual C++ Compiler November 2012 CTP」で追加された6つの新機能

@IT

  1. Vista時代のVisual C++の流儀(前編)Vista到来。既存C/C++資産の.NET化を始めよう!
  2. Vista時代のVisual C++の流儀(中編)MFCから.NETへの実践的移行計画
  3. Vista時代のVisual C++の流儀(後編) STL/CLRによるDocument/Viewアーキテクチャ
  4. C++開発者のための単体テスト入門 第1回 C++開発者の皆さん。テスト、ちゃんとしていますか?
  5. C++開発者のための単体テスト入門 第2回 C++アプリケーションの効率的なテスト手法(CppUnit編)
  6. C++開発者のための単体テスト入門 第3回 C++アプリケーションの効率的なテスト手法(NUnit編)

AWARDS


Microsoft MVP
for Visual Developer - Visual C++


Wankuma MVP
for いぢわる C++


Nyantora MVP
for こくまろ中国茶

Xbox

Links

記事カテゴリ

書庫

日記カテゴリ

安定なソート

ネタ元 → 5つのDateTime変数から、直近のものを選び出す方法

    string[] data = {
      "0", "00", "000", "0000", "00000",
      "1", "11", "111", "1111", "11111",
      "2", "22", "222", "2222", "22222",
      "3", "33", "333", "3333", "33333",
    };

こんなデータを"文字列の長さ"順に並べ替えます。

Array.Sort(data,delegate (string x, string y) { return x.Length - y.Length;});
Console.WriteLine("Array.Sort");
foreach ( string item in data ) Console.WriteLine(item);

僕の環境ではこんな結果となりました。

1
2
0
3
22
33
11
00
000
222
...

確かに文字列長の順にはなってますけど、キレイじゃありません。
等値な二つを並べるとき、もともとの順序を保つソートを"安定なソート:stable sort"
と称しています。 Array.Sortは安定なソートじゃないんですな。

安定なソートを実現する(でもちょっと重い)には、添え字ごとソートしちゃえばいぃです。
つまり、要素を比較して等しかったときは添え字の若い方を小さいとするわけっす。
ちょいちょいとこしらえてみましょ。

using System;

// 添え字つきデータ
struct Indexed<T> : IComparable {
  public T   data;
  public int index;
  public Indexed(T d, int i) { data = d; index = i; }
  public static Comparison<T> compare;
  // 比較結果が0(等値)のときは添え字を比較する
  public int CompareTo(object other) {
    int result = compare(data, ((Indexed<T>)other).data);
    if ( result == 0 ) result = index - ((Indexed<T>)other).index;
    return result;
  }

}

public class Program {

  // 安定なソート
  static public void StableSort<T>(T[] array, Comparison<T> comp) {
    Indexed<T>.compare = comp;
    Indexed<T>[] iarray = new Indexed<T>[array.Length];
    // 添え字つきデータをこしらえ
    for ( int i = 0; i < array.Length; ++i ) {
      iarray[i] = new Indexed<T>(array[i],i);
    }
    // ソートして
    Array.Sort(iarray);
    // 差し戻す
    for ( int i = 0; i < array.Length; ++i ) {
      array[i] = iarray[i].data;
    }
  }

  public static void Main() {
    string[] master = {
      "0", "00", "000", "0000", "00000",
      "1", "11", "111", "1111", "11111",
      "2", "22", "222", "2222", "22222",
      "3", "33", "333", "3333", "33333",
    };
    string[] data;

    data = (string[])master.Clone();
    Array.Sort(data,delegate (string x, string y) { return x.Length - y.Length;});
    Console.WriteLine("Array.Sort");
    foreach ( string item in data ) Console.WriteLine(item);

    data = (string[])master.Clone();
    StableSort(data,delegate (string x, string y) { return x.Length - y.Length;});
    Console.WriteLine("StableSort");
    foreach ( string item in data ) Console.WriteLine(item);
  }
}

投稿日時 : 2008年2月15日 12:50

コメントを追加

# re: 安定なソート 2008/02/15 13:52 ghost_shell

せんせーい!

添え字配列作って、比較を(上と同じ様に)2段階にしたものを作り、添え字で取り出せばいい・・・

単純にできると思うのですが、オブジェクト指向じゃないからダメですかー?

リンクがないけどネタ元は「C# と VB.NET の質問掲示板」ですね。

# re: 安定なソート 2008/02/15 14:01 επιστημη

えーと、
string[] data = { .... };
int[] index = { 0, 1, 2, ... };
を用意しといて data[i]とindex[i]とを連動して比較/交換を行うってスンポーですかしら。

# リンク貼っときましたー

# re: 安定なソート 2008/02/15 14:11 ghost_shell

>えーと、
>string[] data = { .... };
>int[] index = { 0, 1, 2, ... };
>を用意しといて data[i]とindex[i]とを連動して比較/交換を行うってスンポーですかしら。

そうです。
ソート中のdataの方の交換は不要ですね。
やるとおかしくなりますし。

# WHkFmRMyuKohraRA 2012/01/07 14:03 http://www.luckyvitamin.com/p-30350-devita-natural

Not bad post, leave it at my bookmarks!...

タイトル
名前
URL
コメント