• 締切済み

VB Shell sort

初心者です。 シェルソート後の数字がうまく表示できません。 見よう見まねでしているので、どこがどうおかしいのかわかりません。 大変、恐縮ですが宜しくお願いいたします。 ----------------------------------------- Public Class Form1 Dim intNumber() As Integer = {2, 6, 4, 8, 10, 12, 89, 45, 37} Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'Display unsorted numbers to lists For i As Integer = 0 To 8 lstShell.Items.Add(intNumber(i)) Next End Sub Sub btnSort2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSort2.Click Dim i As Integer, j As Integer, k As Integer Dim temp As Integer Dim gap As Integer Dim count As Integer gap = count / 2 Do While gap > 0 k = 0 Do While k < gap j = k + gap Do While j < count i = j - gap Do While i >= k If intNumber(i + gap) > intNumber(i) Then temp = intNumber(i + gap) intNumber(i + gap) = intNumber(i) intNumber(i) = temp Else Exit Do End If i = i - gap Loop j = j + gap Loop k = k + 1 Loop gap = gap / 2 Loop 'Display numbers to list lstShell.Items.Clear() For i As Integer = 0 To 8 lstShell.Items.Add(intNumber(i)) Next End Sub End Class

みんなの回答

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

一応動作はしますが、 > Dim intNumber() As Integer = {2, 6, 4, 8, 10, 12, 89, 45, 37} これを例えば Dim intNumber() As Integer = {2, 6, 4, 8, 10, 12, 89, 45, 37, 51, 13, 63, 34} 等と変更したとします。 現行のままでは期待通りに動作しません。 あちらこちら修正しないといけないですよね。 > For i As Integer = 0 To 8 > Dim count As Integer = 9 このような直接数値を記入するのはできるかぎり避けましょう。 VBなら UBound関数で配列の添字の最大が求められます。 For i As Integer = 0 To UBound(intNumber) Dim count As Integer = UBound(intNumber) +1 等とすれば、intNumberだけ変更すれば関連する箇所が全部変わります。 同様の理由で、折角最初のプログラムで変数countを使っていたのに、修正版で > gap = 9 / 2 > Do While j < 9 と直接 9 と入れてしまっているのは改悪です。

Doremifasolala
質問者

お礼

詳しい説明でわかりやすくご教示いただき、ありがとうございました。 VBのクラスを週一で大学で1月から受講していますが、まだ、勉強不足で、 全くの素人なのに、ShellとBubble Sortの課題が出てしまい、 焦っていました。VBの基本的なこともまだ理解できていないので、 すごく、勉強になりました。大変ありがとうございました。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

> Dim count As Integer > gap = count / 2 countに値が入っていません。

Doremifasolala
質問者

お礼

どうしようもないミスを指摘していただき、ありがとうございました。 色々と手直しして、やっとソート出来ました。大変、感謝いたします。 ----- Public Class Form1 Dim intNumber() As Integer = {2, 6, 4, 8, 10, 12, 89, 45, 37} Dim i As Integer Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'Display unsorted numbers to lists For i As Integer = 0 To 8 lstShell.Items.Add(intNumber(i)) Next End Sub Sub btnSort2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSort2.Click Dim z As Integer, j As Integer, k As Integer Dim temp As Integer Dim gap As Integer Dim count As Integer = 9 gap = 9 / 2 Do While gap > 0 k = 0 Do While k < gap j = k + gap Do While j < 9 z = j - gap Do While z >= k If intNumber(z + gap) < intNumber(z) Then temp = intNumber(z + gap) intNumber(z + gap) = intNumber(z) intNumber(z) = temp Else Exit Do End If z = z - gap Loop j = j + gap Loop k = k + 1 Loop gap = gap / 2 Loop 'Display numbers to list lstShell.Items.Clear() For i As Integer = 0 To 8 lstShell.Items.Add(intNumber(i)) Next End Sub End Class

関連するQ&A

  • VB 2008: Do Whie...Loop文について

    Function FileGetChar(ByVal f As String, ByVal p As Integer) As String   Dim i As Integer = 1   Dim j As Integer = 0   Dim l As Integer   Dim n As Integer = FreeFile()   Dim c As Char   If File.Exists(f) Then     FileOpen(n, f, OpenMode.Random, OpenAccess.Read, , 1)     l = FileLen(f)     Do While (i + j <= l)       FileGet(n, c, i + j)       j = j - (Math.Abs(Asc(c)) > 255)       i = i + 1       If i > p Then         Exit Do       Else         c = ""       End If     Loop     FileClose(n)   End If   Return c End Function [イミディエイトウインドウ] ? FileGetChar("D:\Temp\Test.txt",1) "1" ? FileGetChar("D:\Temp\Test.txt",2) "2" と、一応は動作しています。 l------->ファイル長 i+j----->読み込みのカレントポジション p------->読み込み指示ポジション 今、悩んでいるのはDo...Loop文中のIf Else End If の追放。 何か妙手があれば教えて頂きたい。

  • VBA 桁数が混在するソート

    シートやセルを使わず、VBAのみでクイックソートを実装したいのですが 桁数が混在する列だと正しくソートされません。 1 1 10 10 15 2 等と言う結果になります。 元のデータは外部ファイルで修正をかけたくないので VBA内で格納したデータの桁数を調節する等解決策はありますでしょうか? 以下メソッドです Sub QuickSort1(ByRef argAry As Variant, ByVal lngMin As Long, ByVal lngMax As Long, sortnum As Integer) Dim i As Long Dim j As Long Dim vBase As Variant Dim vSwap() As Variant: ReDim vSwap(UBound(argAry)) vBase = argAry(sortnum)(Int((lngMin + lngMax) / 2)) i = lngMin j = lngMax Do Do While argAry(sortnum)(i) < vBase i = i + 1 Loop Do While argAry(sortnum)(j) > vBase j = j - 1 Loop If i >= j Then Exit Do For i3 = 1 To UBound(argAry) vSwap(i3) = argAry(i3)(i) argAry(i3)(i) = argAry(i3)(j) argAry(i3)(j) = vSwap(i3) Next i = i + 1 j = j - 1 Loop If (lngMin < i - 1) Then Call QuickSort1(argAry, lngMin, i - 1, sortnum) End If If (lngMax > j + 1) Then Call QuickSort1(argAry, j + 1, lngMax, sortnum) End If End Sub

  • VB2008: 文字列を逆順にする関数が判らない!

    Sub Main()   Debug.Print(Reverse("ABC") End Sub Function Reverse(ByVal aChars As String) As String   Dim C As Char   Dim I As Integer   Dim J As Integer   Dim L As Integer = aChars.Length - 1   J = L   Do While I < J     C = aChars.Chars(I)     aChars.Remove(I, 1)     aChars.Insert(I, aChars.Chars(J))     aChars.Insert(J, C)     aChars.Remove(J + 1, 1)     J -= 1     I += 1   Loop   Return aChars End Function 1、"ABC"の"A"を変数 C に保存。 2、"ABC"の"A"を削除。 3、"BC" の先頭に"C"を挿入。 4、"CBAC" の3番目(J=2)に変数Cを挿入。 5、"CBAC" の4番(J+1=3)を削除 6、"CBA" を戻り値にセット。 という Reverse 関数ですが動作しません。 一体、どこでどのように考え違いをしているのでしょうか? 全くわかりません。 宜しくお願いします。

  • エクセルVBAの繰り返し処理の質問

    C列にある項目とG列にある項目を比較して、 一致し、H列にある数字が10以上ならば、B列にフラグ1を立てる という処理を行いたいんですが、 下記ぐらいまでしか作れず、うまくいきません・・・ Sub フラグを立てる処理() Dim i As Integer Dim j As Integer Dim k As Integer i = 1 j = 1 Do j = j + 1 Do i = i + 1 If Cells(j, 8) > 9 Then Cells(i - 1, 4) = 1 End If Loop Until Cells(i, 3) <> Cells(j, 7) Or Cells(i, 3) = "" Loop Until Cells(j, 7) = "" End Sub わかる方がいらっしゃいましたら、お願いします。

  • VB2008: リストメンバーの列数の求め方?

    Sub Main()   Dim I As Integer   Dim J As Integer   Dim K As Integer   Dim aDatas As New List(Of String())()   Dim N = CSVReadToArray("D:\Temp\付属一覧.csv", aDatas) - 1   K = aDatas(0).Count - 1   For I = 0 To N     For J = 0 To K       Debug.Print(aDatas(I)(J))     Next J   Next I End Sub 質問1、K = aDatas(0).Count - 1 の本当のやり方? 質問2、K の処理のされ方。 K が変数としてメモリに配置されることはないと推察しています。 多分、何がしかのスタック領域に一時的に置かれると・・・。 この辺りに関しても教えてもらえれば幸いです。

  • VBA 九九 Do While

    VBAのDo Whileステートメントを使って九九の表をつくりたいのですが、何度やっても途中で詰まり、実行に至りません。 For NextとDo untilではできたと思うのですがDo Whileがどうしてもわからなくて… どなたか助けてください。お願いします。 Sub 九九計算_for() Dim i, j As Integer For i = 1 To 9 For j = 1 To 9 Cells(i, j).Value = i * j Next Next End Sub Sub 九九計算_do_until() j = 1 Do i = 1 Do Cells(j, i).Value = i * j i = i + 1 Loop Until i = 10 j = j + 1 Loop Until j = 10 End Sub

  • VB添削

    このプログラムは 例えば3 3 4とテキストボックスに数字が打ち込まれると 3×3行列が4個分 のテキストボックスがでてきます。 ここに数字を打ち込んでいき、ボタン2を押すと3×3のテキスト トボックスが出てくると同時に足し算した結果が出てくるようにしたいです。 以下のプログラムはできたところまで作成しています。 どこを直せばよいのでしょうか。 Public Class Form1 Private number As Integer Private rows As Integer Private columns As Integer Private Sub Form11_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load For i As Integer = 1 To 3 AddHandler Me.Controls("TextBox" & i).TextChanged, AddressOf TextBox_TextChanged Next End Sub Private Sub TextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) If System.Text.RegularExpressions.Regex.IsMatch(CType(sender, TextBox).Text, "[^0-9]") Then MessageBox.Show("数字で入力してください", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error) With CType(sender, TextBox) .Text = .Text.Substring(0, .Text.Length - 1) .SelectionStart = .Text.Length End With End If Dim cnt1 As Integer Dim cnt2 As Integer Dim cnt3 As Integer If Integer.TryParse(TextBox1.Text, cnt1) And Integer.TryParse(TextBox2.Text, cnt2) And Integer.TryParse(TextBox3.Text, cnt3) Then For k = 1 To cnt3 For i = 1 To cnt1 For j = 1 To cnt2 Dim tb As TextBox = New TextBox() tb.Name = "tb" + i.ToString() Me.Controls.Add(tb) tb.Top = (i - 1) * 28 + 55 tb.Left = (j - 1) * 30 + 40 * (cnt2 * (k - 1)) + 10 tb.Width = 25 Next Next Next End If End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.Bounds = New Rectangle(10, 10, 1350, 800) Me.AutoScroll = True End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim sum As Double Dim cnt As Integer = 0 For i As Integer = 1 To rows For j As Integer = 1 To columns Dim tb As TextBox = New TextBox() cnt += 1 : If cnt > rows * columns Then cnt = 1 tb.Name = "tb" + cnt.ToString Me.Controls.Add(tb) tb.Top = (i - 1) * 30 + (80 + 40 * rows) tb.Left = (j - 1) * 60 + 10 tb.Width = 40 sum = 0 For k As Integer = 1 To number sum += Double.Parse(CType(Me.Controls("tb" + (cnt + (rows * columns * (k - 1))).ToString()), TextBox).Text) Next tb.Text = sum.ToString() Next Next End Sub Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged End Sub Private Sub TextBox2_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox2.TextChanged End Sub Private Sub TextBox3_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox3.TextChanged End Sub End Class

  • 【VB2005】です。txtファイルを配列に読み込もうとしています。

    45*45のtxtデータを配列に読み込もうとしているのですが、エラーが出ます。なぜでしょうか? 宜しくお願いします。 【VB2005を使っています。】 Private Sub OpenButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OpenButton1.Click Dim selectButton As DialogResult Dim filename As String Dim i, j As Integer \'開く ダイアログの表示 selectButton = DBOpenDialog1.ShowDialog() filename = DBOpenDialog1.FileName If selectButton = Windows.Forms.DialogResult.OK Then Dim sr As System.IO.StreamReader = Nothing Dim readFields() As String i = 0 sr = New System.IO.StreamReader(filename, System.Text.Encoding.Default) Do Until sr.EndOfStream readFields = sr.ReadLine().Split(\",\") For j = 0 To 44 Tests1(i, j) = readFields(j) Next j i += 1 Loop sr.Close() End If End Sub

  • クイックソート後の出力(pascal)

    20個の整数データをクイックソートして出力せよ、という課題が出ました。クイックソートまでは出来た(コンパイルできたのでおそらく)のですが、その順に出力する方法がわかりません。どなたかお教えください。 program sort(input,output); const n = 20; type index = 1..n; var A : array[1..n] of integer; i,x,a : integer; p,j,k : index; function PIVOT(i,j : index):integer; var k:index; begin k:=i+1; while (A[i]=A[k]) and (k<=j) do k:=k+1; if k>j then PIVOT:=0 else if A[i]>=A[k] then PIVOT:=i else PIVOT:=k end; procedure SWAP(var x,y:integer); var temp:integer; begin temp:=x; x:=y; y:=temp end; procedure PARTITION(i,j:index; a:integer; var k:index); var l,r:index; begin l:=i; r:=j; while A[l]<a do l:=l+1; while A[r]>=a do r:=r-1; while l<=r do begin SWAP(A[l],A[r]); l:=l+1; r:=r-1; while A[l]<a do l:=l+1; while A[r]>=a do r:=r-1; end; k:=l end; procedure QUICKSORT(i,j:index); var a:integer; p:index; k:index; begin p:=PIVOT(i,j); if p<>0 then begin a:=A[p]; PARTITION(i,j,a,k); QUICKSORT(i,k-1); QUICKSORT(k,j) end end; begin i:=0; i:=1+1; for i:= 1 to n do begin A[i]:=0; end; i:=0; i:=i+1; for i:= 1 to n do begin readln(x); A[i]:=x end; a:=PIVOT(p,j); PARTITION(p,j,A[a],k); QUICKSORT(p,j) end. QUICKSORT(p,j)とend. の間に出力方法を書き込みたいのです。

  • VBプログラム エラーが出ます

    Public Class Form1 Private number As Integer Private rows As Integer Private columns As Integer Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click If Not Integer.TryParse(TextBox1.Text, rows) OrElse _ Not Integer.TryParse(TextBox2.Text, columns) OrElse _ Not Integer.TryParse(TextBox3.Text, number) Then MessageBox.Show("数字で入力してください", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error) Exit Sub End If Me.Bounds = New Rectangle(10, 10, 1300, 800) Dim cnt As Integer = 0 For k As Integer = 1 To number For i As Integer = 1 To rows For j As Integer = 1 To columns Dim tb As TextBox = New TextBox() cnt += 1 tb.Name = "tb" + cnt.ToString() Me.Controls.Add(tb) tb.Top = (i - 1) * 30 + 80 tb.Left = (j - 1) * 60 + 70 * (columns * (k - 1)) + 10 tb.Width = 50 Next Next Next End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim sum As Double Dim cnt As Integer = 0 For i As Integer = 1 To rows For j As Integer = 1 To columns Dim tb As TextBox = New TextBox() cnt += 1 : If cnt > rows * columns Then cnt = 1 tb.Name = "tbA" + cnt.ToString Me.Controls.Add(tb) tb.Top = (i - 1) * 30 + (80 + 40 * rows) tb.Left = (j - 1) * 60 + 10 tb.Width = 40 sum = 0 For k As Integer = 1 To number sum += Double.Parse(CType(Me.Controls("tb" + (cnt + (rows * columns * k-1))).ToString(), TextBox).Text)    エラー Next tb.Text = sum.ToString() Next Next End Sub Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click Do Until Me.Controls.Count <= 6 For Each tbD As Object In Me.Controls If CType(tbD, Control).Name Like "tb*" Then Me.Controls. Remove(tbD) Next Loop End Sub End Class エラーと書いている箇所 どう直したらよいのでしょうか。 縮小変換しないで呼び出されるアクセス可能なitemがないためオーバーロードの解決に失敗しました と出ます。 あとwindowsの画面の大きさを入力される値が小さければ少し小さいwindowsになるように変えたいのですがどうしたよいのでしょう。