|
版主
  
- 帖子
- 2314
- 精华
- 2
- 性别
- 男
- 注册时间
- 2007-10-9
|
5#
大 中
小 发表于 2007-11-16 10:04 只看该作者
这个程序1个半小时就写好了,注释写了半个小时
这种算法,只要理解清楚了,写起来还是比较快的
关键就是要注意递归时候的现场保护和恢复,其他的倒是没啥.
复制内容到剪贴板代码:<br>;快速排序<br>;作者:永夜的极光<br>;时间:2007-11-15</P>
<P>;程序运行结果:<br>;Please input data(0<data<=255)<br>;Divide with any char except 0~9:<br>;15 100 50 105 205 120 30 200<br>;Befor quick sort:15,100,50,105,205,120,30,200<br>;After quick sort:15,30,50,100,105,120,200,205<br>;Press any key to exit...</P>
<P>assume ds:data,cs:code,ss:stack<br>data segment<br> inf0 db 0dh,0ah,'Please input data(0<data<=255)',13,10,'Divide with any char except 0~9:',13,10,'$'<br> buf db 250,?,250 dup ('0') ;保存输入数据字符串的缓冲区<br> table db 100 dup (0) ;分析输入的字符串,分解为数字,保存在这个表中<br> buf2 db 250 dup (0) ;将数组转换成可以显示的字符串,每个数字用逗号分隔,保存在这里,方便显示<br> len db ? ;保存数组长度<br> inf1 db 0dh,0ah,'Befor quick sort:$'<br> inf2 db 0dh,0ah,'After quick sort:$'<br> inf4 db 13,10,'Find another num(Y/N)?$'<br> inf_end db 13,10,'Press any key to exit...$'<br>data ends</P>
<P>stack segment<br> dw 80 dup (0)<br>stack ends</P>
<P>code segment<br>start:<br> mov ax,data<br> mov ds,ax<br> mov es,ax<br> mov ax,stack<br> mov ss,ax<br> call main ;调用主函数<br> <br> lea dx,inf_end ;提示按任意键结束<br> mov ax,0900H<br> int 21H<br> mov ax,0700H<br> int 21H<br> mov ax,4c00H<br> int 21H</P>
<P>main proc near<br> <br> lea dx,inf0 ;提示输入字符串,并接受输入,存在buf<br> mov ah,09H<br> int 21H<br> lea dx,buf<br> mov ah,0aH<br> int 21H<br> <br> call SaveToArray ;调用函数,处理输入的字符串,整理为数字数组<br> lea dx,[inf1] ;提示语句<br> mov ah,09H<br> int 21H<br> lea si,[table] ;传递两个参数,调用函数在屏幕上显示数组<br> lea di,[buf2]<br> call DisplayArray<br> lea di,[table] ;下面5句使di指向数组的最后一个数字<br> mov al,[len]<br> mov ah,0<br> add di,ax<br> dec di<br> call QuickSort ;调用快速排序函数,直接整理数组里面的元素<br> lea dx,[inf2] ;提示语句<br> mov ah,09H<br> int 21H<br> lea si,[table] ;调用函数,显示数组<br> lea di,[buf2]<br> call DisplayArray<br> ret<br>main endp</P>
<P>;函数功能:对于si和di范围内的数字进行整理,使左边的所有数都不大于右边的任意一个,返回中间位置的指针<br>;输入参数:si 指向待整理范围的第一个数字,而且也以这个数字作为分界,比这个数字大的放右边,比他小的放左边<br>; di 指向待整理范围的最后一个数字<br>;输出参数:dx 指向整理后的中间数字,在他左边的数字都不大于他右边的任意一个数字<br>Partition proc near<br> <br> push si<br> push di<br> push ax<br> mov al,[si] ;保存第一个数字,作为比较大小的标准<br> dec si ;si后移,因为下面循环的第一步是si前移,所以要先后移一位,不然会以后第一个数<br> inc di ;di前移,原因如上<br> P_l1:<br> P_l2:<br> dec di ;di前移,如果[di]比标准数字大,则继续循环,这个循环结束后,di指向从右边开始第一个比标准数字小的数字(如果存在的话)<br> cmp [di],al<br> ja P_l2<br> P_l3:<br> inc si ;si后移,如果[si]比标准数字小,则继续循环,这个循环结束后,di指向从右边开始第一个比标准数字大的数字(如果存在的话)<br> cmp [si],al<br> jb P_l3<br> cmp si,di ;如果此时si>=di,那么跳出循环,整理结束<br> jnb P_s1<br> mov ah,[di] ;这三句是交换[si]和[di]<br> xchg [si],ah<br> mov [di],ah<br> jmp P_l1 ;如果si还是小于di,那么继续开始循环,知道整理结束<br> P_s1:<br> mov dx,di ;现在di指向中间元素,赋值个dx,作为返回值<br> pop ax<br> pop di<br> pop si<br> ret</P>
<P>Partition endp</P>
<P>;函数功能:对si和di范围内的数组进行排序<br>;输入参数:si 指向排序范围的第一个数字<br>; di 指向排序范围的最后一个数字<br>;输出参数:无<br>QuickSort proc near<br> <br> push si ;寄存器入栈,保护现场<br> push di<br> push dx<br> cmp si,di ;如果si>=di,则直接返回<br> jge return<br> call Partition ;调用函数,整理数组,返回值dx,在dx左边的数字都不大于右边的数字<br> push di ;保存di<br> mov di,dx ;对于si和bx范围内的数组,递归调用本函数<br> call QuickSort<br> pop di ;取出di<br> mov si,dx ;对dx+1和di范围内的数组,递归调用本函数<br> inc si<br> call QuickSort<br>return:<br> pop dx ;寄存器出栈,恢复现场<br> pop di<br> pop si<br> ret</P>
<P>QuickSort endp</P>
<P>;函数功能:把si指向的数组,转变成一个显示的字符串,并输出<br>;输入参数:si 指向需要处理的数组<br>; di 保存转换后字符串的位置<br>;输出参数:无(直接在屏幕上显示字符串)<br>DisplayArray proc near<br> <br> push ax ;寄存器入栈<br> push bx<br> push cx<br> push dx<br> push di<br> push si<br> <br> mov cl,[len] ;设置循环次数等于数组元素个数<br> mov ch,0<br> push di ;di指向的是存放转换后字符串的地方,这个地方最后赋值给dx,可以显示<br> DA_l1: ;因为每个数字最多为三位,所以下面直接进行处理,不写通用的转换程序<br> mov al,[si] ;当前处理的数字放入ax<br> mov ah,0<br> mov bl,100 ;16位除8位的除法<br> div bl<br> cmp al,0 ;如果商为0,跳转到处理余数的部分<br> jz DA_s1<br> add al,'0' ;商不为0,则加上30H,放入di指向的位置,di后移<br> mov [di],al <br> inc di<br> mov al,ah ;把余数除10,然后ax加上3030H,在用16位长度放入[di]中<br> mov ah,0<br> mov bl,10<br> div bl<br> add ax,3030H<br> mov word ptr [di],ax<br> add di,2<br> mov byte ptr [di],',' ;后面加逗号<br> inc di ;di后移<br> inc si ;已经一个数字处理结束,si后移<br> jmp DA_s3 ;跳到loop的地方<br> DA_s1:<br> mov al,ah ;数字不是三位数,把余数放入al,再除10<br> mov ah,0<br> mov bl,10<br> div bl<br> cmp al,0 ;比较商是否为0,如果为0,说明是一位数,跳转到下面<br> jz DA_s2<br> add al,'0' ;如果商不为0,则是两位数,商加30H,放入[di],di后移<br> mov [di],al<br> inc di<br> DA_s2:<br> add ah,'0' ;把余数加上30H,放入[di],di后移<br> mov [di],ah<br> inc di<br> mov byte ptr [di],',' ;放入逗号<br> inc di<br> inc si ;一个数字处理完成,si后移<br> DA_s3:<br> loop DA_l1 ;继续处理下一个数字<br> dec di ;现在字符串最后一位是逗号,把这个逗号换成'$'就好了<br> mov byte ptr [di],'$'<br> pop dx ;把指向字符串第一个字符的位置出栈,赋值给bx<br> mov ah,09H ;调用中断输出<br> int 21H<br> pop si ;寄存器出栈<br> pop di<br> pop dx<br> pop cx<br> pop bx<br> pop ax<br> ret</P>
<P>DisplayArray endp</P>
<P>;函数功能:把输入的字符串整理为数组<br>;输入参数:无<br>;输出参数:cx 整理出来的数组长度,数组存放在table里面<br>SaveToArray proc near<br> <br> mov cl,[buf+1] ;输入字符串的长度<br> mov ch,0<br> lea si,[buf+2] ;指向输入字符串的起始位置<br> lea di,[table] ;指向存放整理后数字的位置<br> mov bh,0 ;bh存放的是数组长度<br> SaveToArray_l1:<br> cmp byte ptr [si],'0' ;如果这个字符不在0~9范围内,说明上一个数字输入结束<br> jb EndOfANum<br> cmp byte ptr [si],'9'<br> ja EndOfANum<br> mov al,[di] ;如果这个字符是数字字符,那么把原来的值乘10,加上这个数字,减去30H<br> mov bl,10<br> mul bl<br> mov bl,[si]<br> sub bl,'0'<br> add al,bl<br> mov [di],al ;保存回去<br> jmp short continue ;继续下一次循环<br> EndOfANum: ;上一个数字输入完毕<br> cmp byte ptr [di],0 ;如果现在[di]的值为0,那不进行处理,因为已经规定,数字不为0<br> jz continue<br> inc di ;如果[di]不为0,则di后移一位<br> inc bh ;数组长度加1<br> continue:<br> inc si ;si后移一位<br> loop SaveToArray_l1 ;循环<br> inc bh ;最后找到的一个数字,还没有计算进数组长度,所以这里加了1<br> mov [len],bh ;数组长度保存到[len]<br> mov cl,bh ;数组长度保存到cx<br> mov ch,0<br> ret</P>
<P>SaveToArray endp</P>
<P>code ends<br>end start<br>
下面c写的快速排序
复制内容到剪贴板代码:<br>/*****************************************<br>函数功能:快速排序<br>作者:永夜的极光<br>调用:QuickSort(a,p,r)<br>其中 a为待排序数组的数组名,p为排序范围的第一个数字的下标,r为最后一个数字的下标<br>*****************************************/<br>int Partition(int a[],int p,int r)<br>{<br> int x=a[p],i=p-1,j=r+1;<br> while(1)<br> {<br> do<br> {<br> j--;<br> }while(a[j]>x);<br> do<br> {<br> i++;<br> }while(a[i]<x);<br> if(i<j)<br> {<br> int tmp=a[i];<br> a[i]=a[j];<br> a[j]=tmp;<br> }<br> else<br> return j;<br> }<br>}</P>
<P>void QuickSort(int a[],int p,int r)<br>{<br> if(p<r)<br> {<br> int q=Partition(a,p,r);<br> QuickSort(a,p,q);<br> QuickSort(a,q+1,r);<br> }<br>}<br>
[此贴子已经被作者于2007-11-16 10:14:07编辑过]
从BFS(Breadth First Study)到DFS(Depth First Study)
严重鄙视一切把论坛当成作业生成器和人肉搜索引擎的人
|