2016-12-10 7 views
1

Я пытаюсь реализовать алгоритм сортировки слиянием в MIPS, используя связанные списки. Я в основном пытаюсь перевести этот код: http://www.geeksforgeeks.org/merge-sort-for-linked-list/ Однако у меня возникают некоторые проблемы. Сортированный список неполный, как если бы он потерял всю рекурсивную ветвь, например, это связанный список для сортировки: 4 -> 3 -> 1 -> 2 И результат: 1 -> 2 -> 4 . И затем появляется ошибка, когда я пытаюсь записать список в файл (исключение времени выполнения в 0x004003fc: адрес вне диапазона 0x00000000). Я предполагаю, что это потому, что я ожидаю напечатать 4 числа, но у меня только 3 числа в списке.Перевести сортировку слияния со связанными списками с C на MIPS

Я думаю, где мне нужна помощь в функции MergeSort, так как я НЕ ПОЛНОСТЬЮ понимаю, что на самом деле делает указатель. Это то, что я думаю:

Он получает в качестве параметра указатель на указатель на голову списка. Внутри функции он создает указатель «head», и он указывает на значение VALUE в headRef (в этом случае головка была передана по основному, так что теперь «голова» внутри функции имеет адрес головы в главном). Затем он объявляет два указателя: a и b (в MIPS это будет похоже на a = 0, а b = 0? Я не могу «объявить» регистры). Затем он проверяет, имеет ли список 1 или 0 элементов и возвращается, если это произойдет. В противном случае он разбивает список на две половины с FrontBackSplit (head, & a, & b), но это сложный элемент ... эта функция ничего не возвращает. Вместо этого он изменяет указатели «a» и «b», чтобы они указывали на первую половину списка и вторую половину соответственно. В MIPS я бы подумал, что это два возвращаемых значения $ v0 и $ v1. Затем он сортирует список рекурсивно, начиная слева, но еще раз, он ничего не возвращает ... он изменяет указатель «a» и «b». Наконец, он изменяет значение указателя на начало списка, чтобы он указывал на новый отсортированный список.

Из-за так много ** ptr и & значений ptr, я смущен тем, что нужно сохранять в стеке. Это то, что я до сих пор знаю относительно этой функции:

# void mergesort(node** headRef) 
# input $a0: head of the list 
mergesort: 
    move $t0, $s3    # node* head = headRef 
    li  $t1, 0     # node* a 
    li  $t2, 0     # node* b 
    # if(head == NULL || head->next == NULL) 
    beqz $t0, mergesort_return 
    lw  $t3, node_next($t0)  # $t3 = head->next 
    beqz $t3, mergesort_return 

    move $a0, $t0 
    move $a1, $t1 
    move $a2, $t2 
    # save head and $ra 
    addi $sp, $sp, -8 
    sw  $t0, 0($sp) 
    sw  $ra, 4($sp) 
    jal  frontbacksplit 
    # restore head and $ra 
    lw  $t0, 0($sp) 
    lw  $ra, 4($sp) 
    addi $sp, $sp, 8 
    # save output results 
    move $t1, $v0    # a now points to the first half + 1 (if odd) of the list (frontRef) 
    move $t2, $v1    # b now points to the second half of the list (backRef) 

    # save head, a, b and $ra 
    addi $sp, $sp, -16 
    sw  $t0, 0($sp) 
    sw  $t1, 4($sp) 
    sw  $t2, 8($sp) 
    sw  $ra, 12($sp) 
    # mergesort(a) 
    move $a0, $t1 
    jal  mergesort 
    # restore registers and $ra 
    lw  $t0, 0($sp) 
    lw  $t1, 4($sp) 
    lw  $t2, 8($sp) 
    lw  $ra, 12($sp) 
    addi $sp, $sp, 16 

    # save head, a, b and $ra 
    addi $sp, $sp, -16 
    sw  $t0, 0($sp) 
    sw  $t1, 4($sp) 
    sw  $t2, 8($sp) 
    sw  $ra, 12($sp) 
    # mergesort(b) 
    move $a0, $t2 
    jal  mergesort 
    # restore registers and $ra 
    lw  $t0, 0($sp) 
    lw  $t1, 4($sp) 
    lw  $t2, 8($sp) 
    lw  $ra, 12($sp) 
    addi $sp, $sp, 16 

    move $a0, $t1 
    move $a1, $t2 
    # save head, a, b and $ra 
    addi $sp, $sp, -16 
    sw  $t0, 0($sp) 
    sw  $t1, 4($sp) 
    sw  $t2, 8($sp) 
    sw  $ra, 12($sp) 
    jal  sortedmerge 
    # restore registers and $ra 
    lw  $t0, 0($sp) 
    lw  $t1, 4($sp) 
    lw  $t2, 8($sp) 
    lw  $ra, 12($sp) 
    addi $sp, $sp, 16 

    move $s3, $v0  # s3 is the saved head of the original list declared in main 

mergesort_return: 
    jr  $ra 

ответ

0

Хорошо ... Я сделал это. Это было домашнее задание и не было оценено. Надеюсь, они не думают, что я скопировал это.

######### uses function frontbacksplit 
######### WORKING 
# mergesort 
# input $a0: head of the list to merge 
mergesort: 
    li  $t0, 0  # head_one = NULL 
    li  $t1, 0  # head_two = NULL 
    # base case 
    beqz $a0, mergesort_return 
    lw  $t2, node_next($a0) 
    beqz $t2, mergesort_return 

    addi $sp, $sp, -8 
    sw  $ra, 0($sp) 
    sw  $a0, 4($sp) 

    # move $a0, $a0 
    move $a1, $t0 
    move $a2, $t1 
    jal  frontbacksplit 
    move $t0, $v0 
    move $t1, $v1 

    lw  $ra, 0($sp) 
    lw  $a0, 4($sp) 
    addi $sp, $sp, 8 


    # mergesort(a) 
    addi $sp, $sp, -16 
    sw  $ra, 0($sp) 
    sw  $t0, 4($sp) 
    sw  $t1, 8($sp) 
    sw  $a0, 12($sp) 

    move $a0, $t0 
    jal  mergesort # mergesort(a) 
    move $t9, $v0 

    lw  $ra, 0($sp) 
    lw  $t0, 4($sp) 
    lw  $t1, 8($sp) 
    lw  $a0, 12($sp) 
    addi $sp, $sp, 16 

    # mergesort(b) 
    addi $sp, $sp, -20 
    sw  $ra, 0($sp) 
    sw  $t0, 4($sp) 
    sw  $t1, 8($sp) 
    sw  $a0, 12($sp) 
    sw  $t9, 16($sp) 

    move $a0, $t1 
    jal  mergesort # mergesort(b) 
    move $t8, $v0 

    lw  $ra, 0($sp) 
    lw  $t0, 4($sp) 
    lw  $t1, 8($sp) 
    lw  $a0, 12($sp) 
    lw  $t9, 16($sp) 
    addi $sp, $sp, 20 
    # t8 = a, t9 = b 

    addi $sp, $sp, -24 
    sw  $ra, 0($sp) 
    sw  $t0, 4($sp) 
    sw  $t1, 8($sp) 
    sw  $a0, 12($sp) 
    sw  $t9, 16($sp) 
    sw  $t8, 20($sp) 

    move $a0, $t8 
    move $a1, $t9 
    jal  merge 

    lw  $ra, 0($sp) 
    lw  $t0, 4($sp) 
    lw  $t1, 8($sp) 
    lw  $a0, 12($sp) 
    lw  $t9, 16($sp) 
    lw  $t8, 20($sp) 
    addi $sp, $sp, 24 

    #move $v0, $v0 

    jr  $ra 

mergesort_return: 
    move $v0, $a0 
    jr  $ra 


######### WORKING 
# input $a0: source node (list to split) 
# input $a1: front ref (a) $s4 
# input $a2: back ref (b) $s5 
# output $v0: frontRef 
# output $v1: backRef 
frontbacksplit: 
    # $a0 = node* source, $a1 = node* frontRef, $a2 = node* backRef 
    move $t0, $a0    # $t0 = source 
    move $t1, $a1    # $t1 = frontRef 
    move $t2, $a2    # $t2 = backRef 

    li  $t3, 0     # node* fast; 
    li  $t4, 0     # node* slow; 
    # if(source == NULL) 
    beqz $t0, frontbacksplit_sorted 
    lw  $t5, node_next($t0)  # $t5 = source->next 
    # if(source->next == NULL) 
    beqz $t5, frontbacksplit_sorted 
    # else 
    move $t4, $t0    # slow = source 
    lw  $t3, node_next($t0)  # fast = source->next 

frontbacksplit_while: 
    # while(fast != NULL) 
    beqz $t3, frontbacksplit_endwhile 
    lw  $t3, node_next($t3)  # fast = fast->next 
    # if(fast != NULL) 
    beqz $t3, frontbacksplit_while 
    lw  $t4, node_next($t4)  # slow = slow->next 
    lw  $t3, node_next($t3)  # fast = fast->next 
    j  frontbacksplit_while 

frontbacksplit_endwhile: 
    move $t1, $t0    # frontRef = source 
    lw  $t2, node_next($t4)  # backRef = slow->next 
    sw  $zero, node_next($t4) # slow->next = NULL 

    move $v0, $t1 
    move $v1, $t2 
    j  frontbacksplit_end 

frontbacksplit_sorted: 
    move $v0, $t0    # frontRef = source 
    li  $v1, 0     # backRef = NULL 

frontbacksplit_end: 
    jr  $ra 


############ WORKING 
# input $a0: head of the first list 
# input $a1: head of the second list 
# output $v0: pointer to the head of the merged-sorted list 
merge: 
    beqz $a0, merge_return2 
    beqz $a1, merge_return1 
    li  $t3, 0   # head_three = NULL 

    lw  $t0, node_int($a0) 
    lw  $t1, node_int($a1) 

    addi $sp, $sp, -16 
    sw  $ra, 0($sp) 
    sw  $a0, 4($sp) 
    sw  $a1, 8($sp) 
    sw  $t3, 12($sp) 

    bge  $t0, $t1, merge_else 

    # if head_one->num < head_two->num 
    lw  $a0, node_next($a0) 
    # $a1 already has head_two 
    jal  merge 
    move $t0, $v0  # ptr = merge(head_one->next, head_two) 
    # restore values 
    lw  $ra, 0($sp) 
    lw  $a0, 4($sp) 
    lw  $a1, 8($sp) 
    lw  $t3, 12($sp) 

    move $t3, $a0 
    sw  $t0, node_next($t3) 
    move $v0, $t3 
    addi $sp, $sp, 16 
    jr  $ra 

merge_else: 
    # $a0 already has head_one 
    lw  $a1, node_next($a1) 
    jal  merge 
    move $t0, $v0  # ptr = merge(head_one->next, head_two) 
    # restore values 
    lw  $ra, 0($sp) 
    lw  $a0, 4($sp) 
    lw  $a1, 8($sp) 
    lw  $t3, 12($sp) 

    move $t3, $a1 
    sw  $t0, node_next($t3) 
    move $v0, $t3 
    addi $sp, $sp, 16 
    jr  $ra 

merge_return1: 
    move $v0, $a0 
    jr  $ra 

merge_return2: 
    move $v0, $a1 
    jr  $ra 

Я знаю, что это довольно грязно, но это работает: P.

+0

Поздравляем вас с поиском решения самостоятельно. Для учебных целей для других пользователей, у которых может быть аналогичная проблема, вам может быть приятно отредактировать ваш ответ здесь, чтобы подробно рассказать о том, что вы исправили из вашего первоначального вопроса. Кроме того, другие проблемы, с которыми вы столкнулись [и исправлены] и т. Д. Кроме того, что вы узнали и/или улучшили. –

+0

Я сделаю это, как только у меня будет больше времени: D. Может быть, на следующей неделе. – Sebasuraa