Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
how to sort negative and positive values ?
#1
I have an array with positive values and want to sort the array from negative to positive in ascending order but the negative values in descending order
suppose I have  [-1.65068012389, -0.524647623275, 1.65068012389, 0.524647623275]
I want  [ -0.524647623275, -1.65068012389 , 0.524647623275, 1.65068012389]
Reply
#2
Just sort it so all negative numbers are in the first half then the positive in the 2nd.  then sort the 1/2's as you wish them !

   This code here is from QBasic with DOS 5.0 but it's still a great sorting primer !


Attached Files
.bas   SORTDEMO.BAS (Size: 22.51 KB / Downloads: 9)
Reply
#3
Once you have a basic sorting operation, the trick is to realise you can make the "less than" operation mean whatever you want it to mean. Here's a standard sort routine (adapted from the SORTDEMO.bas in the previous response):
Code: (Select All)
Randomize Timer

Dim a(10)
For i = 0 To 10
    a(i) = Int(Rnd * 100) - 50
Next i

Print "Original array"
For i = 0 To 10
    Print a(i);
Next i
Print


QuickSort a(), LBound(a), UBound(a)

Print "Sorted array"
For i = 0 To 10
    Print a(i);
Next i


Function sortrule (a, b)
    sortrule = a < b
End Function


Sub QuickSort (arr() As Single, low, high)
    If low < high Then
        ' Only two elements in this subdivision; swap them if they are out of
        ' order, then end recursive calls:
        If high - low = 1 Then
            If sortrule(arr(high), arr(low)) Then Swap arr(low), arr(high)
        Else

            ' Pick a pivot element at random, then move it to the end:
            pivot = low / 2 + high / 2
            Swap arr(high), arr(pivot)
            partition = arr(high)
            Do

                ' Move in from both sides towards the pivot element:
                I = low: J = high
                Do While (I < J) And (arr(I) = partition Or sortrule(arr(I), partition))
                    I = I + 1
                Loop
                Do While (J > I) And (arr(J) = partition Or sortrule(partition, arr(J)))
                    J = J - 1
                Loop

                ' If we haven't reached the pivot element, it means that two
                ' elements on either side are out of order, so swap them:
                If I < J Then
                    Swap arr(I), arr(J)
                End If
            Loop While I < J

            ' Move the pivot element back to its proper place in the array:
            Swap arr(I), arr(high)

            ' Recursively call the QuickSort procedure (pass the smaller
            ' subdivision first to use less stack space):
            If (I - low) < (high - I) Then
                QuickSort arr(), low, I - 1
                QuickSort arr(), I + 1, high
            Else
                QuickSort arr(), I + 1, high
                QuickSort arr(), low, I - 1
            End If
        End If
    End If
End Sub

The function 'sortrule' defines what it means for a to be 'less than' b. So for your application, you need a sortrule that says negative numbers sort the oppose way to positive numbers:
Code: (Select All)
Function sortrule (a, b)
    If a < 0 And b < 0 Then sortrule = b < a Else sortrule = a < b
End Function

Replace that in the main code above and see it gives output something like this:
Code: (Select All)
Original array
-17 -24  4  37 -40  22 -43  32  41  2 -23
Sorted array
-17 -23 -24 -40 -43  2  4  22  32  37  41

I haven't checked if there's a noticeable speed penalty for using a helper function like this, but if there is you can easily replace all calls to it with the expression inline.
Reply
#4
I'd do this in the following type manner, personally, as I find it to be more intuitive to my own style personally:

Code: (Select All)
Dim d(-10 To 10)
For i = -10 To 10
    d(i) = i
    Print d(i), 'print the jumbled up order
Next
Print

'sort
Dim newLow(0 To 21)
Dim newHigh(0 To 21)
For i = -10 To 10 'seperte lows from highs
    Select Case Sgn(d(i))
        Case -1
            newlow = newlow + 1
            newLow(newlow) = d(i)
        Case 1
            newhigh = newhigh + 1
            newHigh(newhigh) = d(i)
        Case 0: zero = zero + 1
    End Select
Next


BubbleSortAbs newLow(), newlow 'sort the lows
BubbleSortAbs newHigh(), newhigh 'sort the highs

count = -10
For i = 1 To newlow 'rebuild with the lows
    d(count) = newLow(i)
    count = count + 1
Next
For i = 1 To zero 'rebuild with the 0s
    d(count) = 0
    count = count + 1
Next
For i = 1 To newhigh 'rebuild with the 0s
    d(count) = newHigh(i)
    count = count + 1
Next

For i = -10 To 10
    Print d(i), 'print the sorted order
Next
Print

Sub BubbleSortAbs (a(), finish) 'sort by ABS value
    For i = 1 To finish
        For j = i + 1 To finish
            If Abs(a(i)) > Abs(a(j)) Then Swap a(i), a(j)
        Next
    Next
End Sub

This is as simple as can be.  

First we make our data array.
Then we scan it and make two new data arrays -- one for negative values, one for positive values.
Then we sort those two arrays by ABS value so they're in the order we want.
And finally we just put those two arrays back together into a single sorted array in the proper order.

Luke mentioned a speed penalty...   I...  I honestly think this might be *FASTER* than a regular bubble sort would be, in many cases.  

LOL -- and I'm *NOT* crazy to say that!!

Bubblesorts are notoriously inefficient.  The bigger the array size to sort, the worse they become.  In this case, we're cutting our array sizes in half (assumingly, since the data in this case is perfectly balanced in negative and positive values).  I would imagine that with large amounts of data, such as 1,000,000 entries, this would be faster than a plain bubblesort.

After all, this would do 2 * 500,000 bubblesorts, whereas a plain bubblesort would do 1,000,000 sorts.

Of course, if you're using Bubblesort on such large arrays of data, speed probably isn't your primary concern to start with.  I just thought I'd mention mention the difference in outcomes in this case.  Luke is worried his might cause some performance hit.  On the other hand, with the sorting I'm doing, this will probably be a performance BOOST.

And that's the beauty and oddity of programming!  Big Grin
Reply
#5
thanks a million Luke and ahenry3068
@luke your code is perfect
@SMcNeill thank you Smile
Reply
#6
Sort all numbers using abs and then move the negatives ti the begginning
Code: (Select All)

Dim tn As Integer
tn = 10 ' total numbers
Dim n(tn) As Single, i As Integer
Randomize Timer
For i = 1 To tn
    n(i) = (Rnd * 10 + 1) - 5
    Print n(i)
Next i

Print "---------------"
10:
For i = 1 To tn - 1
    If Abs(n(i)) > Abs(n(i + 1)) Then Swap n(i), n(i + 1): GoTo 10
Next i

20:
For i = 1 To tn - 1
    If n(i) >= 0 And n(i + 1) < 0 Then Swap n(i), n(i + 1): GoTo 20
Next i

For i = 1 To tn
    Print n(i)
Next i
Reply
#7
@2112
brilliant ! Smile
Reply
#8
@2112
your code is very compact and efficient, but I have grown reluctant to using Goto so I asked DeepSeek for advice and here's the answer
note substitute boolean with integer
Code: (Select All)

' Bubble sort for absolute values
Dim swapped As Boolean
swapped = True
While swapped
    swapped = False
    For i = 1 To tn - 1
        If Abs(n(i)) > Abs(n(i + 1)) Then
            Swap n(i), n(i + 1)
            swapped = True
        End If
    Next i
Wend

' Bubble sort for sign separation (positive then negative)
swapped = True
While swapped
    swapped = False
    For i = 1 To tn - 1
        If n(i) >= 0 And n(i + 1) < 0 Then
            Swap n(i), n(i + 1)
            swapped = True
        End If
    Next i
Wend
note: the comments are from DeepSeek, all I said was
Code: (Select All)
can you eliminate the goto's in the following Basic code?
10:
For i = 1 To tn - 1
    If Abs(n(i)) > Abs(n(i + 1)) Then Swap n(i), n(i + 1): GoTo 10
Next i

20:
For i = 1 To tn - 1
    If n(i) >= 0 And n(i + 1) < 0 Then Swap n(i), n(i + 1): GoTo 20
Next i
Reply
#9
Hi, Jack...
I like the "goto" statement but in this case the
"while/wend" is a lot faster in sorting many numbers.
The goto is really very slow...
Reply
#10
I don't suppose a Select Case would work here?

Select Case Value

  Case =>0 
   Sort Assending Order

  Case <0
   Sort Decending Order

End Select
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Question on a Quick Sort routine Dimster 4 1,009 09-25-2023, 12:29 PM
Last Post: bplus
  Having trouble Windows command line SORT via SHELL GTC 19 4,367 08-26-2023, 04:19 AM
Last Post: GTC

Forum Jump:


Users browsing this thread: 1 Guest(s)