ab.com コミュニティ

ActiveBasicを通したコミュニケーション
現在時刻 - 2024年4月20日(土) 01:49

全ての表示時間は UTC+09:00 です




新しいトピックを投稿する  トピックへ返信する  [ 106 件の記事 ]  ページ移動 1つ前へ 1 2 3 4 58 次へ
作成者 メッセージ
投稿記事Posted: 2005年8月27日(土) 22:03 
たびたび、申し訳ありません。

 どうも添付したcsvファイルが思惑どおりのイメージになりません。

 修正方法や、添付ファイルとしての投稿方法を教えてください。

 (フォーラムの方向性は変えたくありません・・・)

 また、csvデータのイメージはお解りいただけると思いますので、
 テストデータとしては、ソート済み、逆ソート済みでなければ、
実行時間は変わらないと思います。


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年8月27日(土) 23:02 
>私の使っているクイックソートのコード(Ver2.59)
>正順or逆順に非常に弱いのが欠点

>クイック スタック不足で強制終了

なんだか、クイックが不当な評価を受けていますが、コードが悪いのでは?
普通にクイックを組んだとしても、クイックというのは正順or逆順に対して
相当強いし、スタックについても、50回再帰までokとすると100兆個の
データでもイケます。クイックは、そんなにヤワではないです。

>シェル法が最強
そういうこと書かれると困るんですよねえ。
NlogNとn^1.25(≒N(logN)^2)の差は、データ数が大きくなると
ちょっとやそっとではひっくり返せなくなるだけの差があります。
だから、数千個までなら、シェル法はクイックやヒープとかなりいい勝負を
しますが、数十万個になると、シェル法は脱落する筈です。
クイックやヒープを実験しないうちに最強を決め手はダメだってば。

> abのバージョンがわからず、コンパイルエラーの嵐
私も悩まされています。
で、N88BASICまで遡っても使える命令だけで書いています。
(Do~Loop UntilはIf~gotoに修正する必要があるのと、
 行番号を適当にくっつける必要があるが。)
よって、
・メインルーチンの中で、gosubで飛ばす
という使い方なら、abのVerにかかわらず問題ないはずです。
abは、N88BASIC互換と書いてあるから、
N88BASICで動いてabで動かないというプログラムがあれば、
それはabのバグのせいであり、abのVerを言っても仕方ありません。
※でも、実際問題、コケるため、サブルーチンとして書くことを放棄しました。
 だから、昔の方法(gosubで飛ばし、変数は全てメインと共用)で使ってください。


クイックソート(昔流の書き方で、再帰や構造体は用いていない。)

dim Key(xxx),X,W as ○○○
dim SL(xx),SR(xx) as long
dim i,j,S,L,R,N as long
dim nn as long

'N:データ数
'Key():キーデータの配列
'SL(),SR() スタック配列
'SL()とSR()の配列サイズは以下のとおり。
'nn=log(N)/log(2)+2
'dim SL(nn),SR(nn) as long
'  ただし、ノーマル版はこれより大きい配列が必要。

'Quicksortノーマル版(非再帰)
   S=1 : SL(1)=1 : SR(1)=N
   Do
    L=SL(S) : R=SR(S) : S=S-1
    Do
     i=L : j=R : X=Key((L+R)\2)
     Do
      While Key(i)<X : i=i+1 : WEND
      While X<Key(j) : j=j-1 : WEND
      IF i<=j Then
       W= Key(i) :Key(i)=Key(j) : Key(j)=W
       i=i+1 : j=j-1
      End If      
     Loop Until i>j
     IF i<R Then S=S+1 : SL(S)=i : SR(S)=R
     R=j
    Loop Until L>=R
   Loop Until S=0
   Return

'Quicksort改1 スタックオーバーを起こさないよう変更
   S=1 : SL(1)=1 : SR(1)=N
   Do
    L=SL(S) : R=SR(S) : S=S-1
    i=L : j=R : X=Key((L+R)\2)
    Do
     While Key(i)<X : i=i+1 : WEND
     While X<Key(j) : j=j-1 : WEND
     If i<=j Then
      W= Key(i) :Key(i)=Key(j) : Key(j)=W
      i=i+1 : j=j-1
     End If      
    Loop Until i>j
'    左右のうちデータ数の少ないほうを先に砕く
    If (R-i) > (j-L) Then
     If i<R Then S=S+1 : SL(S)=i : SR(S)=R
     If j>L Then S=S+1 : SL(S)=L : SR(S)=j
    Else
     If j>L Then S=S+1 : SL(S)=L : SR(S)=j
     If i<R Then S=S+1 : SL(S)=i : SR(S)=R
    End If
   Loop Until S=0
   Return

'Quicksort改2 ある程度小さく砕いたら、あとは単純挿入法にまかせる
   nn=20  'ここまで砕いた時点で停止する(この値で適当かどうかは不明)
   S=1 : SL(1)=1 : SR(1)=N
   Do
    L=SL(S) : R=SR(S) : S=S-1
    i=L : j=R : X=Key((L+R)\2)
    Do
     While Key(i)<X : i=i+1 : WEND
     While X<Key(j) : j=j-1 : WEND
     If i<=j Then
      W= Key(i) :Key(i)=Key(j) : Key(j)=W
      i=i+1 : j=j-1
     End If      
    Loop Until i>j
'    左右のうちデータ数の少ないほうを先に砕く
    If (R-i) > (j-L) Then
     If i+nn<R Then S=S+1 : SL(S)=i : SR(S)=R
     If j>L+nn Then S=S+1 : SL(S)=L : SR(S)=j
    Else
     If j>L+nn Then S=S+1 : SL(S)=L : SR(S)=j
     If i+nn<R Then S=S+1 : SL(S)=i : SR(S)=R
    End If
   Loop Until S=0
'
   For i=2 to N
     X=Key(i) : Key(0)=X
     j=i-1
    While X<Key(j)
      Key(j+1)=Key(j): j=j-1
     Wend
     Key(j+1)=X
   Next
   RETURN


'Quicksort改3 最悪計算量に陥る可能性を減らす。
X=Key((L+R)\2)の部分を、
・XはKey(L)とKey((L+R)\2)とKey(R)のうちの中央値を選ぶ
・XはKey(L)、Key(L+1)、とKey(L+2)、...Key(R)のうちからランダムに1つ選ぶ
のいずれかに変更する。


'Quicksort改4 キーが文字列で、データ数が非常に多い場合専用。
1.まず、キーの1文字目を使って、度数ソートで区間分けする。
2.各々の区間に対してQuicksort。


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年8月27日(土) 23:41 
投稿した記事の編集方法はhttp://www.discoversoft.net/forum/faq.php#15にあるようですが、ID登録した人以外は出来ないようですね。
CSVファイル自体はどこかのアップローダーにアップロードしてそのURLを投稿するか、
もしくはCSVファイルを圧縮し、BASE64や昔懐かしいISHでエンコードしたものを投稿してみてはいかがでしょうか。

さて最速のソート法は、安定である必要があるならマージソート、
そうでなければクイックソートですかね。


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年8月28日(日) 01:09 
オフライン

登録日時: 2005年8月23日(火) 00:15
記事: 161
お住まい: 沖縄県
今回、抜き出しがうまくいったと思われる616件分のデータをソートした結果、ファイルの入出力を含めて、60ms前後で処理できました。
ActiveBasic4.x

投稿ロジックにバグが多くて申し訳ありません。

元プログラムが(第1列=自治体CD(01固定)、第2列=住民CD)のCSVファイルを第2列でソートする仕様でした。
今回、投稿用に第1列をソート対象に改造し、出力結果をチェックしましたが、結果的に第1列に関する処理にバグを大量に作り込みました。
以後投稿時は、十分にチェックを行います。m(_^_)m

PS
実は、自分もCSVの高速ソートが必要になったのでActiveBasic(Ver4.x)を使ってみようと思ったのです。
(趣味で開発を行っているので、有償の開発ツールを買うお金が無いのです)
でも、ActiveBasicに出会えて非常によかったと思うので、自分のノウハウは全て公開しようと思っています。

これからもよろしくお願いします。

必要ないと思いますが、訂正後のコードも乗せておきます。
(本当は、以前に乗せたコードは全て消したいのですが・・・)

条件
[AB4]プロジェクト・EXE - ノーマルウィンドウベース
コマンドを実行する為に、CommandButton1が必要です。
fLoad(処理対象のCSVファイルを指定する)


最後に編集したユーザー マティ [ 2005年12月15日(木) 23:22 ], 累計 1 回

通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年8月28日(日) 12:29 
オフライン

登録日時: 2005年5月31日(火) 17:59
記事: 899
お住まい: 東京都
前回のコードはAB 2.62用でしたが、omasuさんのcsvはなぜかエラー。
デバッガもないのでAB 4.1β1用に移植しました。

コンパイルして実行するとソートは20ミリ秒になりました。
クイックソートですが、まだ他の種類を試していないので直接的な比較はまだできませんが、少なくともAB2よりは相当速くなっています。
H17.11.26
コードが長いのでhideを使用するように修正いたしました。


最後に編集したユーザー イグトランス [ 2005年11月26日(土) 14:31 ], 累計 2 回

通報する
ページトップ
 記事の件名: 近況報告について
投稿記事Posted: 2005年8月28日(日) 17:37 
いつもお世話になっております。

 イグトランスさんのメッセージでAB(4.1β1)を早速ダウンロードしました。
 入出力のファイル名の変更だけで実行ができました。
 入力データ件数は「Const TableSize = 2000」の変更で実行できました。

 あまりにもソート時間が短く、愛機の環境でも、数十ミリセカンドの世界で実行可能です。(一瞬、実行結果を疑ったほどです。)
 今、結果の1行目が空白になってしまう原因を追求中です。

 自作のプログラムでは1000件の配列変数(テーブル)セットが2秒もかかるのに「なーぜー」?、
 それより早い時間でソートができるのかが雲の上の世界と感じます。

 AB2.62は数千件のデータを配列変数に取り込めるのに、「実行プログラムが64KB以上になる」
 AB4.xx以降ではエラーとなるかが不明です。「exeでありながら、comモデル?」
 (~↓~)フォーラムの方向性は変えたくありません。

 勝手ながらテストデータを
数値4桁を文字列として扱い10000件を実行した結果を以下に示します。

 ソート時間 デバック 1.604秒 exe 0.426秒
 残念ながら配列変数(テーブル)にためこむロジックはエラーとなります。


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年8月28日(日) 19:21 
オフライン

登録日時: 2005年8月23日(火) 00:15
記事: 161
お住まい: 沖縄県
omasuさん、自分のコードは実行してくれないのですね(泣)

しかたがないので、イグトランスさんのソートが早い理由を説明すると、
コード:
If lstrcmp(KeyTable[Index[First]], KeyTable[Index[j]]) > 0 Then

(中略)

    Swap(Index[Center], Index[First])
omasuさんのコードは、
コード:
    If keytbl$(p1)>keytbl$(j) Then

    (中略)

        Swap keytbl$(i),keytbl$(p1)
        Swap datatbl$(i),datatbl$(p1)
ここで重要なのは、最初に指摘した通り
 omasuさんのプログラムは、文字列をSwap
 イグトランスさんは、文字列を指定するIndexをSwap

omasuさんのが最初に出したアルゴリズムでも、IndexをSwapする方法に変更すると劇的に性能が改善します。
コード:
    Dim Index(tblcnt)
    For i=0 To tblcnt
        Index(i)=i
    Next

    (中略)

    If keytbl$(Index(p1))>keytbl$(Index(j)) Then

    (中略)

        Swap(Index, Index[p1])


今後性能を改善しようと思うと、CSVファイルの読込みから書込みまでの
全工程を見直す必要が出てくると思います。

ちなみに、最終提示したプログラムの処理性能は、
BubbleSort以外は処理時間(10ms未満)でしたのでファイルの入出力を含めたシステム性能(60ms前後)として計測しました。

P.S
引用:
今、結果の1行目が空白になってしまう原因を追求中です。

配列の0からデータを設定しましたか?
配列の1からデータを設定していませんか?

[/quote]


通報する
ページトップ
投稿記事Posted: 2005年8月28日(日) 19:47 
申し訳ありません。

マティさんへ

 「実行してくれない」のではなく実行能力がないのが現状です。

条件
[AB4]プロジェクト・EXE - ノーマルウィンドウベース
コマンドを実行する為に、CommandButton1が必要です。
fLoad(処理対象のCSVファイルを指定する)

 アクティブベーシック4.0のプロジェクトにボタンを作成、
イベントコードのイベントプロシージャにマティさんのコードを埋め込みました。

 デバックを実行するも
MainWnd.sbp(31) - "TextSort_DestroyObjects" 無効な識別子です

 かねてからソースレベルでの作成はしてきましたが、プロジェクトの概念がなく
 ただいま勉強中でありますm(_ _)m

現在 自分が吸収、実行可能なロジックはソースのみとなっています。
申し訳ありません。


通報する
ページトップ
   
投稿記事Posted: 2005年8月28日(日) 19:57 
オフライン

登録日時: 2005年5月31日(火) 17:59
記事: 899
お住まい: 東京都
> MainWnd.sbp(31) - "TextSort_DestroyObjects" 無効な識別子です
これは「プロジェクト名_DestroyObjects」と命名されます。
なのでプロジェクト名をTextSortにしていないとうまくいきません。
プロジェクト名が違う場合、自分で「プロジェクト名_DestroyObjects」に書き換えれば動くと思います。

ちなみに私が実行するとシェルソート1, 2もコムソートも50ミリ秒台、バブルソートは100ミリ秒台になりました。
(timeGetTimeを使うように修正してあります)


通報する
ページトップ
 記事の件名: 動きました!!
投稿記事Posted: 2005年8月28日(日) 20:48 
お世話になります。

 AB 4.1β1での実行
 Const xMax = 300000のため変更なし
 処理速度は4桁10000件でデバックにて852msでした。

しかし、
 実行結果が入力データと出力結果が一緒のためまた悩んでいます。

4.0で実行すべきでしょうか?


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年8月28日(日) 21:16 
オフライン

登録日時: 2005年8月23日(火) 00:15
記事: 161
お住まい: 沖縄県
ごめんなさい、omasuさん
2ページ目の2005年08月28日(日) 01に投稿したプログラムを使用してください。
その前のプログラムはソート条件に誤りがあって、自分の環境で偶然動いていたものです。

ActiveBasic 4.1B2で実行してもOKでした。

クイックソートについても、皆さんの投稿を参考に調査を行っていますが・・・
自分の処理環境(27万件中、最初の7万件と中間に11万件の連続データがある)と相性が悪いため、本来の高速性を生かしきれていません。
もう少し研究したいと思います。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年8月30日(火) 00:24 
イグトランスさんのクイックソートですが、やや効率が悪いです。
データ数1000個の場合の比較回数、入替え回数を計測、数値は概数。
Keytable,Indexに関係するもののみをカウントし、単なる添字の比較はカウントせず)

イグトランスさんのクイックソート
        比較回数  交換回数
ランダムデータ 11500 6900
昇順データ    8000 5000
降順データ    8600 5700

私のクイックソート(ノーマル版)
        比較回数  交換回数
ランダムデータ  7200 2600
昇順データ    8000  500
降順データ    7000 1000

参考1:シェル法(クヌース改)
        比較回数  交換回数
ランダムデータ 14000 14000
昇順データ    5500  5500
降順データ    9400  9400


参考2:単純挿入法
        比較回数   交換回数
ランダムデータ 250000 250000
昇順データ     1000   1000
降順データ   500000 500000


イグトランスさんのクイックソートのデータ交換回数が必要以上に多いため、
明らかに私のもの(=解説本の標準版)より遅いです。
それでもシェル法よりはわずかに勝っていますが。


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年8月30日(火) 13:48 
オフライン

登録日時: 2005年8月23日(火) 00:15
記事: 161
お住まい: 沖縄県
河川屋さんのコードを正しくインプリメントするとクイックの性能が計測できました。
自分が参考にしたコードが駄目だったようです。

再帰なし 880ms
再帰あり 1280ms(河川屋さんのコードを再帰ありに戻す)
再帰あり 1150ms(最適化2のみ適用)
と言うわけで、クイックの圧勝でした。

今回は非常に勉強になりました。ありがとうございます。

言い訳
googleでクイックソートを検索すると、他の方が投稿したような片側から詰める処理がほとんどでした。
両側から詰める方法も存在は知っていましたが、ネットで調べればすぐにコードも得られるだろうと思っていました。
なかなか落ちていないですね!

目標
日曜日からDBに書き込む処理を勉強しています。
まさか、ODBCドライバの制御から勉強する必要があったなんて・・・。

コードを作成した記念にUPします。


最後に編集したユーザー マティ [ 2005年12月15日(木) 23:23 ], 累計 1 回

通報する
ページトップ
投稿記事Posted: 2005年8月31日(水) 22:34 
実行テストもままならない「ソートロジック大会」なるテーマを掲げてしまい。
高度なロジックの投稿の数々、皆様には大変お世話になりました。

イグトランスさん、河川屋さん、マティさん、淡幻星さん、高信期さん
本当にありがとうございました。(搭乗者順)

また、1000名以上の方々のフォーラム参照に満足しています。

(これで、最後にはしたくありません)

 PertⅡ主催者募集・・・\(~O~)/
 今回の「大会」なるものの、「実行管理委員会」を主催可能な実力者を募集します。
 ※そんな実力者は一番早い?


いつの日か、「私より早い・・・集合」で、・・・あくまで希望ですが・・・


通報する
ページトップ
   
投稿記事Posted: 2005年9月15日(木) 23:07 
オフライン

登録日時: 2005年9月02日(金) 22:15
記事: 96
お世話になります。

あれから、ほとんどのロジックを実行できなかった心残りで、
試行錯誤を繰り返してきました。

中間結果報告という形で、ご報告申し上げます。

実行環境
Cpu Pentium4 周波数2.66GHz メモリ256MByte

テストcsvファイル
 5桁のランダム数字を文字列として使用
 テストデータイメージ
コード:
26859,31003,37839,74441,25822,29003,54011,19579,72420,27675,25111,12762,55130,49720,97371,20405,52912,64265,80288,55299,39913,14589,75082,44182,45705,92357
60841,91092,77067,79925,28514,36197,16786,89574,31012,26270,75320,78494,32872,23085,43516,55354,12531,60530,20124,15771,77757,75784,54270,40216,15173,10227
67670,74412,73156,20065,84922,31690,98540,90588,57296,60254,21653,52591,41306,16425,19665,29547,56820,36166,93903,82901,64051,12796,67288,69641,34454,34565
21540,27936,87912,73621,10468,95213,88320,64498,86489,76019,17807,19912,74595,66107,80508,37801,97051,81810,96331,41196,92766,11529,56718,37673,13557,19144
 キー列   1列目と2列目を連結
 データ列数 26列

実行アクティブベーシック Ver.4.1.β2 最新版

作成者         ソート名称   1000件/秒    5000件/秒    10,000件/秒   65,536件/秒

河川屋さん       クイックノーマル版   0.080      0.220       0.311      1.482
河川屋さん       クイック改1    0.080      0.190       0.331      1.492
河川屋さん       クイック改2    0.092      0.200       0.350      1.502
マティさん       コーム       0.080      0.210       0.320      1.863
イグトランスさん    クイック      0.040      0.240       0.551      4.440
河川屋さん       改シェル法     0.150      0.831       2.002     17.956
omasu          単純選択法     1.402     36.633      145.559    6313.448
淡幻星さん       クイック      ごめんなさい、もう少し、お待ちください m(_ _)m

自分も数万件のソートが可能となりました。
 しかし、まちくたびれました・・・


通報する
ページトップ
期間内表示:  ソート  
新しいトピックを投稿する  トピックへ返信する  [ 106 件の記事 ]  ページ移動 1つ前へ 1 2 3 4 58 次へ

全ての表示時間は UTC+09:00 です


オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[12人]


トピック投稿:  可
返信投稿:  可
記事編集: 不可
記事削除: 不可
ファイル添付: 不可

検索:
ページ移動:  
cron
Powered by phpBB® Forum Software © phpBB Limited
Japanese translation principally by ocean