本篇博客简要的实现了二分搜索和冒泡排序的汇编写法。下面简要的介绍这两种简单的算法。
在计算机科学中,二分查找算法(英语:binary search algorithm),也称折半搜索算法(英语:half-interval search algorithm)、对数搜索算法(英语:logarithmic search algorithm),是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。
二分查找算法在情况下的复杂度是对数时间,进行O(log n)次比较操作(n在此处是数组的元素数量,O是大O记号,log 是对数)。二分查找算法使用常数空间,无论对任何大小的输入数据,算法使用的空间都是一样的。除非输入数据数量很少,否则二分查找算法比线性搜索更快,但数组必须事先被排序。尽管特定的、为了快速搜索而设计的数据结构更有效(比如哈希表),二分查找算法应用面更广。
二分查找算法有许多中变种。比如分散层叠可以提升在多个数组中对同一个数值的搜索。分散层叠有效的解决了计算几何学和其他领域的许多搜索问题。指数搜索将二分查找算法拓宽到无边界的列表。二叉搜索树和B树数据结构就是基于二分查找算法的。
冒泡排序(英语:Bubble Sort)又称为泡式排序,是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。冒泡排序对n个项目需要O(n2)的比较次数,且可以原地排序。尽管这个算法是最简单了解和实现的排序算法之一,但它对于包含大量的元素的数列排序是很没有效率的。冒泡排序是与插入排序拥有相等的运行时间,但是两种算法在需要的交换次数却很大地不同。在最坏的情况,冒泡排序需要O(n2)次交换,而插入排序只要最多O(n)交换。冒泡排序的实现(类似下面)通常会对已经排序好的数列拙劣地运行O(n2),而插入排序在这个例子只需要O(n)个运算。因此很多现代的算法教科书避免使用冒泡排序,而用插入排序取代之。冒泡排序如果能在内部循环第一次运行时,使用一个旗标来表示有无需要交换的可能,也可以把最优情况下的复杂度降低到O(n)。在这个情况,已经排序好的数列就无交换的需要。若在每次走访数列时,把走访顺序反过来,也可以稍微地改进效率。有时候称为鸡尾酒排序,因为算法会从数列的一端到另一端之间穿梭往返。
冒泡排序算法的运作如下:
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,
最后的元素会是最大的数。针对所有的元素重复以上的步骤,除了最后一个。持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。由于它的简洁,冒泡排序通常被用来对于程序设计入门的学生介绍算法的概念。
下面给出冒泡排序以及二分搜索算法的汇编语言实现过程。
BinarySearch.inc
; BinarySearch.inc - prototypes for procedures used in
; the BubbleSort / BinarySearch program.
; Search for an integer in an array of 32-bit signed
; integers.
BinarySearch PROTO,
pArray:PTR DWORD, ; pointer to array
Count:DWORD, ; array size
searchVal:DWORD ; search value
; Fill an array with 32-bit signed random integers
FillArray PROTO,
pArray:PTR DWORD, ; pointer to array
Count:DWORD, ; number of elements
LowerRange:SDWORD, ; lower range
UpperRange:SDWORD ; upper range
; Write a 32-bit signed integer array to standard output
PrintArray PROTO,
pArray:PTR DWORD,
Count:DWORD
; Sort the array in ascending order
BubbleSort PROTO,
pArray:PTR DWORD,
Count:DWORD
FillArray.asm
TITLE FillArray Procedure (FillArray.asm)
INCLUDE Irvine32.inc
.code
;------------------------------------------------------------
FillArray PROC USES eax edi ecx edx,
pArray:PTR DWORD, ; pointer to array
Count:DWORD, ; number of elements
LowerRange:SDWORD, ; lower range
UpperRange:SDWORD ; upper range
;
; Fills an array with a random sequence of 32-bit signed
; integers between LowerRange and (UpperRange - 1).
; Returns: nothing
;-----------------------------------------------------------
mov edi,pArray ; EDI points to the array
mov ecx,Count ; loop counter
mov edx,UpperRange
sub edx,LowerRange ; EDX = absolute range (0..n)
cld ; clear direction flag
L1: mov eax,edx ; get absolute range
call RandomRange
add eax,LowerRange ; bias the result
stosd ; store EAX into [edi]
loop L1
ret
FillArray ENDP
END
PrintArray.asm
TITLE PrintArray Procedure (PrintArray.asm)
INCLUDE Irvine32.inc
.code
;-----------------------------------------------------------
PrintArray PROC USES eax ecx edx esi,
pArray:PTR DWORD, ; pointer to array
Count:DWORD ; number of elements
;
; Writes an array of 32-bit signed decimal integers to
; standard output, separated by commas
; Receives: pointer to array, array size
; Returns: nothing
;-----------------------------------------------------------
.data
comma BYTE ", ",0
.code
mov esi, pArray
mov ecx, Count
cld ; direction = forward
L1: lodsd ; load [ESI] into EAX
call WriteInt ; send to output
mov edx, OFFSET comma
call Writestring ; display comma
loop L1
call Crlf
ret
PrintArray ENDP
END
BubbleSort.asm
TITLE BubbleSort Procedure (BubbleSort.asm)
; Sort an array of signed integers, using the Bubble
; sort algorithm. The main program is in BinarySearchTest.asm.
INCLUDE Irvine32.inc
.code
;----------------------------------------------------------
BubbleSort PROC USES eax ecx esi,
pArray:PTR DWORD, ; pointer to array
Count:DWORD ; array size
;
; Sort an array of 32-bit signed integers in ascending order
; using the bubble sort algorithm.
; Receives: pointer to array, array size
; Returns: nothing
;-----------------------------------------------------------
mov ecx, Count
dec ecx ; decrement count by 1
L1:
push ecx ; save outer loop count
mov esi, pArray ; point to first value
L2:
mov eax, [esi] ; get array value
cmp [esi+4], eax ; compare a pair of values
jge L3 ; if [esi] <= [edi], don't exch
xchg eax, [esi+4] ; exchange the pair
mov [esi], eax
L3:
add esi,4 ; move both pointers forward
loop L2 ; inner loop
pop ecx ; retrieve outer loop count
loop L1 ; else repeat outer loop
L4:
ret
BubbleSort ENDP
END
BinarySearch.asm
TITLE Binary Search Procedure (BinarySearch.asm)
; Binary Search procedure
INCLUDE Irvine32.inc
.code
;-------------------------------------------------------------
BinarySearch PROC USES ebx edx esi edi,
pArray :PTR DWORD, ; pointer to array
Count :DWORD, ; array size
searchVal :DWORD ; search value
LOCAL first :DWORD, ; first position
last :DWORD, ; last position
mid :DWORD ; midpoint
;
; Search an array of signed integers for a single value.
; Receives: Pointer to array, array size, search value.
; Returns: If a match is found, EAX = the array position of the
; matching element; otherwise, EAX = -1.
;-------------------------------------------------------------
mov first, 0 ; first = 0
mov eax, Count ; last = (count - 1)
dec eax
mov last, eax
mov edi, searchVal ; EDI = searchVal
mov ebx, pArray ; EBX points to the array
L1:
; while first <= last
mov eax, first
cmp eax, last
jg L5 ; exit search
; mid = (last + first) / 2
mov eax, last
add eax, first
shr eax, 1
mov mid, eax
; EDX = values[mid]
mov esi, mid
shl esi, 2 ; scale mid value by 4
mov edx, [ebx+esi] ; EDX = values[mid]
; if ( EDX < searchval(EDI) )
; first = mid + 1;
cmp edx, edi
jge L2
mov eax, mid ; first = mid + 1
inc eax
mov first, eax
jmp L4
; else if( EDX > searchVal(EDI) )
; last = mid - 1;
L2:
cmp edx, edi
jle L3
mov eax, mid ; last = mid - 1
dec eax
mov last, eax
jmp L4
; else return mid
L3:
mov eax, mid ; value found
jmp L9 ; return (mid)
L4:
jmp L1 ; continue the loop
L5:
mov eax,-1 ; search failed
L9:
ret
BinarySearch ENDP
END
BinarySearchTest.asm
TITLE Bubble Sort and Binary Search BinarySearchTest.asm)
; Bubble sort an array of signed integers, and perform
; a binary search.
; Main module, calls Bsearch.asm, Bsort.asm, FillArry.asm
INCLUDE Irvine32.inc
INCLUDE BinarySearch.inc ; procedure prototypes
LOWVAL = -5000 ; minimum value
HIGHVAL = +5000 ; maximum value
ARRAY_SIZE = 50 ; size of the array
.data
array DWORD ARRAY_SIZE DUP(?)
.code
main PROC
call Randomize
; Fill an array with random signed integers
INVOKE FillArray, ADDR array, ARRAY_SIZE, LOWVAL, HIGHVAL
; Display the array
INVOKE PrintArray, ADDR array, ARRAY_SIZE
call WaitMsg
; Perform a bubble sort and redisplay the array
INVOKE BubbleSort, ADDR array, ARRAY_SIZE
INVOKE PrintArray, ADDR array, ARRAY_SIZE
; Demonstrate a binary search
call AskForSearchVal ; returned in EAX
INVOKE BinarySearch,ADDR array, ARRAY_SIZE, eax
call ShowResults
call WaitMsg;
exit
main ENDP
;--------------------------------------------------------
AskForSearchVal PROC
;
; Prompt the user for a signed integer.
; Receives: nothing
; Returns: EAX = value input by user
;--------------------------------------------------------
.data
prompt BYTE "Enter a signed decimal integer "
BYTE "to find in the array: ",0
.code
call Crlf
mov edx, OFFSET prompt
call WriteString
call ReadInt
ret
AskForSearchVal ENDP
;--------------------------------------------------------
ShowResults PROC
;
; Display the resulting value from the binary search.
; Receives: EAX = position number to be displayed
; Returns: nothing
;--------------------------------------------------------
.data
msg1 BYTE "The value was not found.",0
msg2 BYTE "The value was found at position ",0
.code
.IF eax == -1
mov edx, OFFSET msg1
call WriteString
.ELSE
mov edx, OFFSET msg2
call WriteString
call WriteDec
.ENDIF
call Crlf
call Crlf
ret
ShowResults ENDP
END main