【问题标题】:How can I make a binary tree?如何制作二叉树?
【发布时间】:2016-05-30 16:11:09
【问题描述】:

我正在做关于 MIPS 的作业,任务是在 MIPS 中创建一个二叉树,它可以接受双精度浮点数并动态分配空间。有没有人可以使用 MIPS 中的二叉树示例?

【问题讨论】:

  • MIPS 和...汇编语言一样吗?
  • 假设你没有写自己的动态分配器,你还没有完全指定你的工作环境。
  • @dmckee 对不起,我不明白你的意思。当我们在做链表的时候,我们用 li $v0,9 syscall 完成了分配

标签: binary-tree mips


【解决方案1】:

如果您知道如何在 MIPS 中创建数组,您可以将二叉树投影到数组上。它或多或少会浪费大量空间,但它会半简单地工作。

首先确定您将如何在堆栈上组织内存中的节点。我会组织它:

[data to store] #presumably floating point numbers
[address of left node]
[address of right node]

为节点指定一个空值,可能是0x7ff...f

指定一个空地址,可能是0

创建一个大小为 : (2^n - 1) * NodeSize
的数组 其中 n = 树的最深分支的深度,从 1 开始计数,而不是 0。NodeSize 是描述节点所需的单词数。

数组的索引将与下面描述的模式相对应。

     0
   /   \
  1     2
 / \   / \
3   4 5   6

使用起来会有些困难,但应该可以。我想从技术上讲,如果你管理好树,你不需要数组来索引空值,或者如果你保持我描述的格式,你真的不需要保存其他节点的地址,因为它们是由他们的索引暗示。所以真的你只需要一个或另一个。你真的应该通过弄清楚你想要使用多少地址以及你的树有多满来选择哪一个更容易。如果您的树已满,则隐含的边有助于节省空间。

tl;dr 这将通过两种方式描述树来浪费空间。删除数组创意或地址。

【讨论】:

    【解决方案2】:

    我有一个类似的项目。

    我的解决方案如下:

    ##################################################
    #
    #   Binary Search Tree - Project 1
    #
    #   First Assembly Program :)
    #
    ##################################################
    .data
    nl: .asciiz "\n"
    prompt1: "\nPlease select an option from the list below:\n"
    prompt2: "[A] - Add a record to the tree\n"
    prompt3: "[F] - Find a record in the tree\n"
    prompt4: "[P] - Perform a preorder traversal\n"
    prompt5: "[I] - Perform an inorder traversal\n"
    prompt6: "[Q] - Quit the program\n"
    prompt7: "\nChoose a character: "
    empty: "\nThe Tree is Empty."
    youentered: "\nYou Entered: "
    recordfound: "\nRecord Found: "
    recordnotfound: "\nRecord Not Found! "
    goodbye: "\nGoodbye!"
    addid: "\nEnter the ID to add: "
    addyear: "Enter the year: "
    addtitle: "Enter the title: "
    adddescription: "Enter the description: "
    id: "\nID: "
    year: "\nYear: "
    title: "\nTitle: "
    description: "Description: "
    #idsize: .word 0
    #optiona: 97    addrecord   a
    #optionf: 102   findrecord  f
    #optionp: 112   preorder    p
    #optioni: 105   inorder     i
    #optionq: 113   quit        q
    ###################################################################
    #
    #   Note: I reuse a lot of print statements
    #   This code is far from what I would call optimized
    #   
    #   This is my first assembly program and I'm really just
    #   Happy to see it all working :)
    #
    #   I spent about 18 hours writing this so lol :)
    #
    #   The only thing that I've gotten to crash it so far is
    #   Entering characters when it's waiting for an int :)
    #
    ######################################################
    #
    #   Here is my memory setup:
    #
    #   $s5 - Stores Root Node
    #   $s7 - Stores Size of Tree (Not Really Necessary)
    #
    #   Each New Item Contains a chunk of 344 bytes
    #   The bytes are setup as such:
    #
    #   8 Bytes - [ID]
    #   8 Bytes - [Year]
    #   64 Bytes - [Title]
    #   256 Bytes - [Description]
    #   8 Bytes - [LeftNodeAddress]
    #   8 Bytes - [RightNodeAddress]
    #
    #
    #   Example Tree:
    #
    #                        10        -Root
    #                      /    \
    #                     7     15     -Branch
    #                    / \   /  \
    #                   6  9  12   17  -Leaf
    #
    #   In Memory:
    #
    #       [Offset: 328] - [ID] - [Offset: 336]
    #             |                       |
    # [Off: 328][ID][Off:336] [Off: 328][ID][Off: 336] . . . 
    #
    #
    ########################################################
    .text 
    ###################
    ##Prompt Function##
    ###################
    prompt:
    li $v0, 4
    la $a0, prompt1         #Please select an option from the list below:
    syscall
    
    li $v0, 4
    la $a0, prompt2         #[A] - Add a record to the tree
    syscall
    
    li $v0, 4
    la $a0, prompt3         #[F] - Find a record in the tree
    syscall
    
    li $v0, 4
    la $a0, prompt4         #[P] - Preorder traversal
    syscall
    
    li $v0, 4
    la $a0, prompt5         #[I] - Inorder traversal
    syscall
    
    li $v0, 4
    la $a0, prompt6         #[Q] - Quit the program
    syscall
    ###################
    ##Get User Input ##
    ################### 
    getinput:   
    li $v0, 4           #Choose a character:
    la $a0, prompt7
    syscall
    
    li $v0, 12          #Read a single character from console
    syscall
    
    move $s0, $v0
    
    beq $s0, 97, addrecord      #If you press 'a', addrecord
    beq $s0, 102, findrecord    #If you press 'f', findrecord
    beq $s0, 112, preorder      #If you press 'p', preorder
    beq $s0, 105, inorder       #If you press 'i', inorder
    beq $s0, 113, exit      #If you press 'q', exit
    
    li $v0, 4           #If you press something random
    la $a0, nl          #Display new line
    syscall
    
    j getinput          #And ask for a new character
    ###################
    ## Add A Record  ##
    ###################
    addrecord:
    li $v0, 9           #allocate memory for new record
    li $a0, 344         #enough memory for 2 addresses and all the data
    syscall
    
    
    move $s0, $v0           #hang onto the initial address of all our info
    
    li $v0, 4           #prompt for ID
    la $a0, addid
    syscall
    
    li $v0, 5           #enter integer
    syscall
    
    sw $v0, 0($s0)          #store our ID into memory   Offset: 0
    
    li $v0, 4           #prompt for add year
    la $a0, addyear
    syscall
    
    li $v0, 5           #enter integer
    syscall
    
    sw $v0, 4($s0)          #store year into our memory Offset: 4
    
    li $v0, 4           #prompt for add title
    la $a0, addtitle
    syscall
    
    li $v0, 8           #read our title into the allocated space
    la $a0, 8($s0)          #Offset: 8
    li $a1, 64
    syscall
    
    li $v0, 4           #prompt for add description
    la $a0, adddescription
    syscall
    
    li $v0, 8           #read our description into the allocated space
    la $a0, 72($s0)         #Offset: 72
    li $a1, 256
    syscall 
    
    bne $s7, 0, setlocations    #if this isn't root node let's set the locations
    
    add $s7, $s7, 1         #add 1 to the size of the records
    
    move $s5, $s0           #store this address as root node for now
    
    j prompt
    ########################
    ##Set Memory Locations##
    ########################
    setlocations:
    move $s6, $s5           #Keep $s5 as  our root and use $s6 as temporary storage
    move $s4, $s6           #Use $s4 to find the null node slot
    storelocations:
    beqz $s4, store         #If we've reached a leaf, store
    lw $t2, 0($s4)          #get ID from current node
    lw $t1, 0($s0)          #get Current ID from new node node we're adding
    ble $t1,$t2,goleft      #get left location if new node <= current node
    move $s6, $s4
    lw $s4, 336($s4)        #get node to the right if new node > current node
    li $t3, 336         #be ready to store to the right slot
    j storelocations
    goleft:
    move $s6, $s4
    lw $s4, 328($s4)        #load the node to the left
    li $t3, 328         #be ready to store to the left slot
    j storelocations
    store:
    beq $t3, 336, storeright    #if $t3 was set to storeRight, then store to the right
    sw $s0, 328($s6)        #else store the new node's location into our node's left slot
    add $s7, $s7, 1         #remind our size register that it's growing
    j prompt            #back to the prompt
    storeright:
    sw $s0, 336($s6)        #store new node to the right slot
    j prompt            #back to the prompt
    ########################
    ## Find Record by ID  ##
    ########################
    findrecord:
    move $s6, $s5
    bne $s7, 0, search
    li $v0, 4           #if tree is empty
    la $a0, empty           #display message Tree is empty
    syscall
    j prompt            #and go wait for input
    search:
    move $s6, $s5
    li $v0, 4           #print ID:
    la $a0, id
    syscall
    
    li $v0, 5           #let user enter ID
    syscall
    
    move $t1, $v0           #store the id we're looking for in $t1
    checkagain: 
    lw $t2, ($s6)           #store the id we're currently looking at
    bne $t1, $t2, checkempty    #if this isn't the right ID, is it the last one?
    ###########################
    ##If we find the record:
    ###########################
    li $v0, 4
    la $a0, recordfound     #Record Found: 
    syscall
    
    li $v0, 4           #Print ID:
    la $a0, id
    syscall
    
    li $v0, 1           #Print the ID stored at $s6     [Offset: 0]
    lw $a0, 0($s6)
    syscall
    
    li $v0, 4           #Print Year:
    la $a0, year
    syscall
    
    li $v0, 1           #Print the Year stored at $s6   [Offset: 4]
    lw $a0, 4($s6)
    syscall
    
    li $v0, 4           #Print Title:
    la $a0, title
    syscall
    
    li $v0, 4           #Print the Title stored at $s6  [Offset: 8]
    la $a0, 8($s6)
    syscall
    
    li $v0, 4           #Print Description:
    la $a0, description
    syscall
    
    li $v0, 4           #Print descript stored at $s6   [Offset: 72]
    la $a0, 72($s6)
    syscall
    
    j getinput
    
    checkempty:
    ble $t1, $t2, checkleft     #If $t1 <= $t2 check the left node
    lw $s6, 336($s6)        #Otherwise check the right node
    bne $s6, 0, checkagain      #If this record isn't empty, check again
    li $v0, 4           #Otherwise
    la $a0, recordnotfound      #Record not found
    syscall
    j getinput
    checkleft:
    lw $s6, 328($s6)        #Check the left node
    bne $s6, 0, checkagain      #If the record isn't empty, check again
    li $v0, 4           #Otherwise
    la $a0, recordnotfound      #Record not found
    syscall
    j getinput
    treeempty:
    li $v0, 4           #if tree is empty
    la $a0, empty           #display message Tree is empty
    syscall
    j prompt
    #####################################
    #
    #   The Inorder Function
    #
    #####################################
    inorder:
    beq $s7, 0, treeempty       #If the tree is empty display empty message
    move $s6, $s5           #$s6 is the record we're currently at
    move $t0, $s6           #t0 will iterate $s6 is our starting node
    move $t1, $t0           #t1 will be thrown on the stack to keep track of everything
    jal printinorder
    j prompt
    printinorder:
    addi $sp, $sp, -12      #allocate 8 bytes for the stack
    sw $ra, 0($sp)          #4 for the $ra variable
    sw $t1, 4($sp)          #4 for $t1
    
    bne $t0, 0, dontreturn      #if $t0 isn't null don't return
    lw $ra, 0($sp)          #otherwise:
    lw $t1, 4($sp)          #pop stack
    addi $sp, $sp, 12       #and prepare
    jr $ra              #to return
    dontreturn:
    move $t1, $t0           #put $t0 in $t1
    lw $t0, 328($t0)        #load the next pointer to the left
    jal printinorder        #and recurse back to printorder
    move $s6, $t1           #if we're back here, it's time to print
    j goprint           #so go print
    afterprint:
    move $t0, $t1           #after we print, move $t1 back to $t0
    lw $t0, 336($t0)        #get the next pointer to the right
    jal printinorder        #recurse to see if it's the last one
    move $s6, $t1           #if we made it here, it is, let's print
    beq $s6, $t1, done      #if we already printed this one, we're done (Root Node)
    j goprint           #Go print the node to the right
    done:
    lw $ra, 0($sp)          #if we're done, pop our stack
    lw $t1, 4($sp)          #clean it up
    addi $sp, $sp, 12       #8 bytes worth
    jr $ra              #and return
    goprint:
    li $v0, 4           #Print ID:
    la $a0, id
    syscall
    
    li $v0, 1           #Print the ID stored at $s6     [Offset: 0]
    lw $a0, 0($s6)
    syscall
    
    li $v0, 4           #Print Year:
    la $a0, year
    syscall
    
    li $v0, 1           #Print the Year stored at $s6   [Offset: 4]
    lw $a0, 4($s6)
    syscall
    
    li $v0, 4           #Print Title:
    la $a0, title
    syscall
    
    li $v0, 4           #Print the Title stored at $s6  [Offset: 8]
    la $a0, 8($s6)
    syscall
    
    li $v0, 4           #Print Description:
    la $a0, description
    syscall
    
    li $v0, 4           #Print descript stored at $s6   [Offset: 72]
    la $a0, 72($s6)
    syscall
    
    j afterprint
    
    #####################################
    #
    #   The Preorder Function
    #
    #####################################
    preorder:
    beq $s7, 0, treeempty       #If the tree is empty display empty message
    move $s6, $s5           #$s6 is the record we're currently at
    move $t0, $s6           #t0 will iterate $s6 is our starting node
    move $t1, $t0           #t1 will be thrown on the stack to keep track of everything
    jal printpreorder
    j prompt
    printpreorder:
    addi $sp, $sp, -12      #allocate 8 bytes for the stack
    sw $ra, 0($sp)          #4 for the $ra variable
    sw $t1, 4($sp)          #4 for $t1
    bne $t0, 0, dontreturnpo    #if $t0 isn't null don't return
    lw $ra, 0($sp)          #otherwise:
    lw $t1, 4($sp)          #pop stack
    addi $sp, $sp, 12       #and prepare
    jr $ra              #to return
    dontreturnpo:
    move $s6, $t0           #if we made it here, it is, let's print
    j goprintpo         #so go print
    afterprintpo:
    move $t1, $t0           #put $t0 in $t1
    lw $t0, 328($t0)        #load the next pointer to the left
    jal printpreorder       #and recurse back to printorder
    move $t0, $t1           #after we print, move $t1 back to $t0
    lw $t0, 336($t0)        #get the next pointer to the right
    jal printpreorder       #recurse to see if it's the last one
    donepo:
    lw $ra, 0($sp)          #if we're done, pop our stack
    lw $t1, 4($sp)          #clean it up
    addi $sp, $sp, 12       #8 bytes worth
    jr $ra              #and return
    goprintpo:
    li $v0, 4           #Print ID:
    la $a0, id
    syscall
    
    li $v0, 1           #Print the ID stored at $s6     [Offset: 0]
    lw $a0, 0($s6)
    syscall
    
    li $v0, 4           #Print Year:
    la $a0, year
    syscall
    
    li $v0, 1           #Print the Year stored at $s6   [Offset: 4]
    lw $a0, 4($s6)
    syscall
    
    li $v0, 4           #Print Title:
    la $a0, title
    syscall
    
    li $v0, 4           #Print the Title stored at $s6  [Offset: 8]
    la $a0, 8($s6)
    syscall
    
    li $v0, 4           #Print Description:
    la $a0, description
    syscall
    
    li $v0, 4           #Print descript stored at $s6   [Offset: 72]
    la $a0, 72($s6)
    syscall
    
    j afterprintpo
    
    exit:
    li $v0, 4           #Say
    la $a0, goodbye         #Goodbye!
    syscall
    
    li $v0, 10          #Terminate Program
    syscall
    

    【讨论】:

      猜你喜欢
      • 2011-05-24
      • 2011-03-24
      • 1970-01-01
      • 1970-01-01
      • 2013-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多