快速排序不能在mips中正确分区

时间:2016-04-21 03:25:21

标签: sorting assembly mips quicksort

好的,对于这个项目,我们必须在C中给出函数快速排序,这是C

中的函数
void quickSort ( int arr [], int left , int right ) {
int index = partition (arr , left , right );

if ( left < index - 1) {
     quickSort (arr , left , index - 1);
}
if ( index < right ) {
     quickSort (arr , index , right );
   }
}

int partition ( int arr [], int left , int right ) {
   int i = left , j = right ;
   int tmp;
   int pivot = arr [( left + right ) / 2];
while (i <= j) {
   while (arr[i] < pivot ) {
      i++;
   }
   while (arr[j] > pivot ) {
      j --;
   }
   if (i <= j) {
     tmp = arr[i];
     arr[i] = arr[j];
     arr[j] = tmp;
     i++;
     j --;
   }
 }
 return i;
}

这是我在MIPS中的功能

.data
out:    .asciiz "The elements sorted in ascending order are: "  #for printing output
comma:  .asciiz ", "                        #for commma between numbers in output
arr:    .space 80                           #space for 20 elements in array 
    .text
Main:       addi $v0, $zero, 5      #set up for reading input(array size)
        syscall             #read integer
        add $s0, $zero, $v0     #$s0 = the size of the array the user entered
        la $s1, arr         #$s1 = base address of array
        addi $t0, $s0, 0        #$t0 = size of array for looping condition
        add $t2, $zero, $s1     #$t2 = base adress array for loop
LoopIns:    beq $t0, $zero, InsE        #when $t0 gets to 0 all elements have been added, end loop
        addi $v0, $zero, 5      #set up for reading integer(to insert into array)
        syscall             #read integer
        addi $t1, $v0, 0        #store integer read in t1
        sw $t1, 0($t2)          #store integer read into array
        addi $t2, $t2, 4        #$t2(arraybase address) = $t2 + 4
        subi $t0, $t0, 1        #decrement looping condition(array size)
        j LoopIns           #jump back to top of loop
InsE:       subi $t3, $s0, 1        #$t3 = array size - 1(right)
        add $a0, $zero, $s1     #$a0 = base adress array(int arr[])
        addi $a1, $zero, 0      #$a1 = 0(left)
        add $a2, $zero, $t3     #$a2 = $t3(right)
        jal quickSort           #run quick sort

        la $a0, out         #load address of output start
        addi $v0, $zero, 4      #set up for printing string
        syscall             #print string
        addi $t4, $s0, 0        #size of array for looping condition
        addi $t5, $s1, 0        #$t3 = arrray base address
PrintLoop:  beq $t4, $zero, PrintLoopEnd    #if array size get to 0 all elements have printed, end loop
        lw $t6, 0($t5)          #t6 = arr[index]
        addi $a0, $t6, 0        #$a0 = arr[index] to print
        addi $v0, $zero, 1      #set up $v0 to print integer
        syscall
        beq $t4, 1, endCom      #if array size == 1, dont print comma
        la $a0, comma           #$a0 = comma to print
        addi $v0, $zero, 4      #set up v0 for printing string
        syscall 
endCom:     addi $t5, $t5, 4        #$t3 = next index in array      
        subi $t4, $t4, 1        #decrement looping condition(array size)
        j PrintLoop         #repeat printing loop
PrintLoopEnd:   addi $v0, $zero, 10     #set up $v0 for clean exit
        syscall             #exit program
#------------------------------------------------------------------------------------------------------------------------
quickSort:  addi $sp, $sp, -16      #make room on stack
        sw $a1, 12($sp)         #save $a1 on stack
        sw $a2, 8($sp)          #save $a2 on stack
        sw $s0, 4($sp)          #save $s0 on stack
        sw $ra, 0($sp)          #save $ra on stack

        jal partition           #jump to partition
        addi $s0, $v0, 0        #index = partition(arr, left, right)
        subi $t0, $s0, 1        #$t0 = index - 1
IfFirst:    slt $t1, $a1, $t0       #$t1 = (left < index - 1) ? 1 : 0
        beq $t1, $zero, IfSecond    # !(left < index - 1) ? 1 : 0
        addi $a2, $s0, -1       #$a2 = index - 1
        jal quickSort           #quickSort(arr, left, index - 1)        #jump to return         
IfSecond:   slt $t2, $s0, $a2       #$t2 = (index < right) ? 1 : 0
        beq $t2, $zero, QuickSortRET    # !(index < right) --> IfSecondEnd
        addi $a1, $s0, 0        #$a1 = index
        jal quickSort           #quickSort(arr, index, right)   

QuickSortRET:   lw $a1, 12($sp)         #restore $a1
        lw $a2, 8($sp)          #restore $a2
        lw $s0, 4($sp)          #restore $s0
        lw $ra, 0($sp)          #restore $ra
        addi $sp, $sp, 16       #pop stack
        jr $ra              #return to caller
#--------------------------------------------------------------------------------------------------------------------------
partition:  addi $sp, $sp, -16      #make room on stack
        sw $s0, 12($sp)         #store $s0 on stack
        sw $s1, 8($sp)          #store $s1 on stack
        sw $s2, 4($sp)          #store $s2 on stack
        sw $s3, 0($sp)          #store $s3 on stack
        add $s0, $zero, $a1     #i($s0) = left
        add $s1, $zero, $a2     #j($s1) = right
        add $t0, $a1, $a2       #$t0 = left + right
        srl $t0, $t0, 1         #$t0 = (left + right)/2
        sll $t0, $t0, 2         #$t0 = ((left + right)/2) * 4
        add $t0, $a0, $t0       #$t0 = address + (((left + right)/2) * 4)
        lw $t0, 0($t0)          #$t0 = arr[(left + right) / 2]
        addi $s3, $t0, 0        #pivot = arr[(left + right) / 2]
OuterWhile: slt $t0, $s1, $s0       #$t0 = (j < i) ? 1 : 0
        bne $t0, $zero, OuterWhEnd

InnerWhile1:    add $t1, $zero, $s0     #$t1 = i
        sll $t1, $t1, 2         #$t1 = i * 4
        add $t1, $a0, $t1       #$t1 = addr + (i * 4)
        lw $t1, 0($t1)          #$t1 = arr[i] 
        slt $t2, $t1, $s3       #$t2 = (arr[i] < pivot) ? 1 : 0
        beq $t2, $zero, InnerWhile2 #!(arr[i] < pivot) --->InnerWhile1End
        addi $s0, $s0, 1        #i = i + 1  
        j InnerWhile1           #jump back to top of loop

InnerWhile2:    add $t3, $zero, $s1     #$t3 = j
        sll $t3, $t3, 2         #$t3 = j * 4
        add $t3, $a0, $t3       #$t3 = address + (j * 4)
        lw $t3, 0($t3)          #$t3 = arr[j]
        slt $t4, $s3, $t3       #$t4 = (pivot < arr[j]) ? 1 : 0
        beq $t4, $zero, OuterIfStart    # !(pivot < arr[j]) --->InnerWhile2End
        subi $s1, $s1, 1        #j = j - 1
        j InnerWhile2           #jump back to top of loop

OuterIfStart:   slt $t2, $s1, $s0       #$t2 = (j < i) ? 1 : 0
        bne $t2, $zero, LoopR       # !(j < i) ---> OuterIfEnd
        add $t1, $zero, $s0     #$t1 = i
        sll $t1, $t1, 2         #$t1 = i * 4
        add $t1, $a0, $t1       #$t1 = address + (i * 4)
        lw $t3, 0($t1)          #$t3 = arr[i]
        add $t4, $zero, $s1     #$t4 = j
        sll $t4, $t4, 2         #$t4 = j * 4
        add $t4, $a0, $t4       #$t4 = address + (j * 4)
        lw $t5, 0($t4)          #$t5 = arr[j]   
        add $s2, $zero, $t3     #tmp = arr[i]
        sw $t5, 0($t1)          #arr[i] = arr[j]
        sw $s2, 0($t4)          #arr[j] = tmp
        addi $s0, $s0, 1        #i = i + 1
        subi $s1, $s1, 1        #j = j - 1
LoopR:      j OuterWhile
OuterWhEnd: addi $v0, $s0, 0        #v0 = i
        lw $s0, 12($sp)         #restore $s0 on stack
        lw $s1, 8($sp)          #restore $s1 on stack
        lw $s2, 4($sp)          #restore $s2 on stack
        lw $s3, 0($sp)          #restore $s3 on stack
        addi $sp, $sp, 16       #pop stack
        jr $ra

每当我在输入7(数组大小)上运行程序,然后是2,5,1,-7,2,4,16时,只返回一些数组。我得到的输出是-7,1,2,2,5,4,16。只有一个元素乱序,我无法通过查看我的代码找出原因。如果有人能帮助我理解为什么这样做会很棒,谢谢。

1 个答案:

答案 0 :(得分:0)

简单地说,使用 do while 循环代替 while 循环可以解决问题。