8086系列(12):折半查找

本文详细介绍了如何用折半查找算法在一个从小到大排列的无符号数组中查找特定数值。通过设置初始查找范围并不断比较目标值与数组中间元素,逐步缩小查找范围,最终找到目标值或确定未找到。代码示例展示了查找过程,并涵盖了各种可能的查找情况,包括找到元素、小于第一个数、大于最后一个数和未找到的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

在附加段中,有一个从小到大顺序排列的无符号数组,其首地址存放在DI寄存器中,数组中的第一个单元存放着数组的长度。在AX中有一个无符号数,要求在数组中查找AX,如找到,CF=0,并在SI中给出该元素在数组中的偏移地址;如未找到,置CF=1

思路

折半查找过程如下:
(1) 初始化被查找数组的首尾下标,low=1,high=n
(2) 若low>high 则查找失败,置CF=1,退出程序
否则计算中点 mid = (low+high)/2
(3) ax与中点元素比较,若ax = r[mid] ,则查找成功,程序结束;
若k<r[mid] 转为步骤四,若k>r[mid] ,转为步骤五
(4) 低半部分查找lower,high = mid-1,返回步骤2,继续查找
(5) 高半部分查找higher,low = mid+1,返回步骤2,继续查找

代码

datasg segment
    low_idx dw ?
    high_idx dw ?
datasg ends
;-----------------
extendsg segment
    array dw 10,0,1,2,3,4,5,6,7,9,10    ;数组的第一个单元存放数组的长度
extendsg ends
;=================
codesg segment
    assume es:extendsg,ds:datasg,cs:codesg
main proc far
start:
    push ds
    sub ax,ax
    push ax
    mov ax,datasg
    mov ds,ax
    mov ax,extendsg
    mov es,ax
    mov ax,3            ;ax中存放待比较的数
;------------------
;compare ax with first number
    cmp ax,es:[di+2]    ;ax和第一个数比较
    ja chk_last         ;大于第一个数
    lea si,es:[di+2]    ;第一个数的偏移地址赋值给si
    je exit             ;ax等于第一个数,CF=0
    stc                 ;ax不等于第一个数,CF=1
    jmp exit
;compare ax with last number
chk_last:
    mov si,es:[di]      ;有几个数
    shl si,1            ;si*2 一个数占两个byte
    add si,di           ;si指向最后一个数
    cmp ax,es:[di]      ;和最后一个数比较
    jb search           ;小于最后一个数,则需要查找
    je exit             ;ax等于最后一个数,CF=0
    stc                 ;ax不等于最后一个数,CF=1
    jmp exit
;Search for value within the list
search:
    mov low_idx,1       ;low_idx 指向第一个数
    mov bx,es:[di]
    mov high_idx,bx     ;high_idx 指向最后一个数
    mov bx,di           ;bx指向数组元素的首地址  (bx+2)为第一个数的地址
mid:    
    mov cx,low_idx
    mov dx,high_idx
    cmp cx,dx
    ja no_match         ;low_idx>high_idx  则退出查找
    add cx,dx
    shr cx,1            ;计算cx = (low_idx+high_idx)/2
    mov si,cx           ;si为(low_idx+high_idx)/2
    shl si,1            ;si*2 指向下一次查找的地址
compare:
    cmp ax,es:[bx+si]   ;mid和ax比较
    je exit             ;相等退出
    ja higher           ;ax>[mid]
lower:
    dec cx              ;cx = (low_idx+high_idx)/2-1
    mov high_idx,cx     ;high_idx = (low_idx+high_idx)/2-1
    jmp mid
higher:
    inc cx              ;cx = (low_idx+high_idx)/2+1
    mov low_idx,cx      ;low_idx = (low_idx+high_idx)/2+1
    jmp mid
no_match:
    stc
;------------------
exit:
    ret
main endp
codesg ends
end start

调试

一、测试ax能找到的情况,ax = 3

在这里插入图片描述能找到,偏移量是8

在这里插入图片描述
二、测试ax小于第一个数的情况

在这里插入图片描述

三、测试ax大于最后一个数的情况

在这里插入图片描述

四、测试ax夹在中间没有找到的情况

ax = 8

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值