堆排序(Heap Sort)
算法思想:
堆的概念
堆:本质是一种数组对象。特别重要的一点性质:
任意的叶子节点小于(或大于)它所有的父节点。对此,又分为大顶堆和小顶堆:
大顶堆要求节点的元素都要大于其孩子。
小顶堆要求节点元素都小于其左右孩子。
两者对左右孩子的大小关系不做任何要求。
利用堆排序,就是基于大顶堆或者小顶堆的一种排序方法。下面,通过大顶堆来实现。
基本思想:堆排序可以按照以下步骤来完成:
1.首先将序列构建称为大顶堆;(这样满足了大顶堆那条性质:
位于根节点的元素一定是当前序列的最大值)
2. 取出当前大顶堆的根节点,将其与序列末尾元素进行交换;
(此时:序列末尾的元素为已排序的最大值;由于交换了元素,
当前位于根节点的堆并不一定满足大顶堆的性质)
3. 对交换后的n-1个序列元素进行调整,使其满足大顶堆的性质;
4. 重复2.3步骤,直至堆中只有1个元素为止
下面是基于大顶堆的堆排序算法代码:
#include <stdio.h>
int Queenes[8]={0},Counts=0;
int Check(int line,int list){
//遍历该行之前的所有行
for (int index=0; index<line; index++) {
//挨个取出前面行中皇后所在位置的列坐标
int data=Queenes[index];
//如果在同一列,该位置不能放
if (list==data) {
return 0;
}
//如果当前位置的斜上方有皇后,在一条斜线上,也不行
if ((index+data)==(line+list)) {
return 0;
}
//如果当前位置的斜下方有皇后,在一条斜线上,也不行
if ((index-data)==(line-list)) {
return 0;
}
}
//如果以上情况都不是,当前位置就可以放皇后
return 1;
}
//输出语句
void print()
{
for (int line = 0; line < 8; line++)
{
int list;
for (list = 0; list < Queenes[line]; list++)
printf("0");
printf("#");
for (list = Queenes[line] + 1; list < 8; list++){
printf("0");
}
printf("\n");
}
printf("================\n");
}
void eight_queen(int line){
//在数组中为0-7列
for (int list=0; list<8; list++) {
//对于固定的行列,检查是否和之前的皇后位置冲突
if (Check(line, list)) {
//不冲突,以行为下标的数组位置记录列数
Queenes[line]=list;
//如果最后一样也不冲突,证明为一个正确的摆法
if (line==7) {
//统计摆法的Counts加1
Counts++;
//输出这个摆法
print();
//每次成功,都要将数组重归为0
Queenes[line]=0;
return;
}
//继续判断下一样皇后的摆法,递归
eight_queen(line+1);
//不管成功失败,该位置都要重新归0,以便重复使用。
Queenes[line]=0;
}
}
}
int main() {
//调用回溯函数,参数0表示从棋盘的第一行开始判断
eight_queen(0);
printf("摆放的方式有%d种",Counts);
return 0;
}
汇编代码
include irvine32.inc
.data
arr dd 3,1,5,7,2,4,9,6,10,8
len dd ($-arr)/4
two dd 2
msg1 db ' ',0
msg2 db '��ʼֵ��',0
msg3 db '�����',0
.code
print proc
push ebp
mov ebp,esp
pushad
mov esi,0
mov ebx,[ebp+8]
again:
cmp esi,[ebp+12]
jge final
mov eax,[ebx+4*esi]
call writeint
mov edx,offset msg1
call writestring
add esi,1
jmp again
final:
popad
pop ebp
ret 8
print endp
HeapAdjust proc
;;HeapAdjust(H[],s,length)
push ebp
mov ebp,esp
pushad
mov esi,[ebp+8];edx:H[]
mov ebx,[ebp+12];ebx:s
mov ecx,[esi+4*ebx];ecx:tmp
mov eax,ebx
mul two
add eax,1;eax:child
again:
cmp eax,[ebp+16];child��length
jge final
mov edx,eax
add edx,1;esi=child+1
cmp edx,[ebp+16];child+1��length
jge next1;;if��H[s]<H[child]��
mov edi,[esi+4*eax];edi:H[child]
cmp edi,[esi+4*edx]
jge next1
add eax,1
next1:;;
mov edx,[esi+4*eax];esi=H[child]
cmp [esi+4*ebx],edx;�Ƚ�H[s]��H[child]
jge final
mov [esi+4*ebx],edx
mov ebx,eax
mov eax,ebx
shl eax,1
add eax,1
mov [esi+4*ebx],ecx;H[s]=tmp
jmp again
final:
popad
pop ebp
ret 12
HeapAdjust endp
BuildingHeap proc
;;BuildingHeap(int H[],int length)
push ebp
mov ebp,esp
pushad
mov eax,[ebp+12];length
sub eax,1
mov edx,0
div two;eax:i
again:
; call crlf
; call writedec
; call crlf
cmp eax,0
jl final
push dword ptr[ebp+12]
push eax
push dword ptr[ebp+8]
call HeapAdjust
sub eax,1
jmp again
final:
popad
pop ebp
ret 8
BuildingHeap endp
HeapSort proc
push ebp
mov ebp,esp
pushad
push dword ptr[ebp+12]
push dword ptr[ebp+8]
call BuildingHeap
mov edx,[ebp+8];H[]
mov esi,[ebp+12]
sub esi,1;esi:i
again:
cmp esi,0
jle final
mov edi,0
mov ebx,[edx+4*esi];ebx:temp
mov ecx,[edx+4*edi];ecx:H[0]
mov [edx+4*esi],ecx
mov [edx+4*edi],ebx
push esi
push edi
push dword ptr[ebp+8]
call HeapAdjust
sub esi,1
jmp again
final:
popad
pop ebp
ret 8
HeapSort endp
main proc
mov edx,offset msg2
call writestring
push len
push offset arr
call print
push len
push offset arr
call HeapSort
mov edx,offset msg3
call writestring
push len
push offset arr
call print
exit
main endp
end main