用堆排序的方法实现将数组中的数字从小到大排列.
编译器:gcc, 编译环境:32位系统可以正常编译; 如果是64位系统请使用 -m32参数, 或修改宏定义中的汇编代码部分.
#include<stdio.h>
#include<stdlib.h>
#include<strings.h>
#define push(x) \
__asm__ volatile ("push %%eax" \
::"a"(x))
#define pop() ({ \
register int _res; \
__asm__ volatile ("pop %%eax" \
:"=a" (_res):); \
_res;})
typedef struct node{
int data;
int seq;
struct node *left;
struct node *right;
}node;
node *head=NULL;
void exchange(node *a,node *b){
int tmp;
tmp=a->data;
a->data=b->data;
b->data=tmp;
}
node *find_node(int i,node *head){
node *p=head;
int digit=0;
int ii=i;
while (ii!=1){
push(ii&1);
digit++;
ii>>=1;
}
while(digit){
if (pop()==1){
p=p->right;
}else{
p=p->left;
}
digit--;
}
return p;
}
int compare_up(int i){
int tmp;
if (i==1)
return 1;
else{
if ( find_node(i/2,head)->data > find_node(i,head)->data){
tmp=find_node(i/2,head)->data;
find_node(i/2,head)->data = find_node(i,head)->data;
find_node(i,head)->data=tmp;
return i/2;
}else{
return i;
}
}
}
void adjust_up(int i){
int tmp;
while(1){
tmp=compare_up(i);
if (tmp==i)
break;
else
i=tmp;
}
}
node *compare_down(node *p){
node *tmp;
if (!p){
return p;
}
if (p->left!=NULL && p->right!=NULL){
if (p->left->data > p->right->data){
tmp=p->right;
}else{
tmp=p->left;
}
if (p->data > tmp->data){
exchange(p,tmp);
return(tmp);
}
}else if (p->left==NULL && p->right!=NULL){
if (p->right->data < p->data){
exchange(p->right,p);
return(p->right);
}
}else if (p->left!=NULL && p->right==NULL){
if (p->left->data < p->data){
exchange(p->left,p);
return(p->left);
}
}
return p;
}
void adjust_down(node *head){
node *tmp;
node *p=head;
while(1){
tmp=compare_down(p);
if (tmp==p)
break;
else
p=tmp;
}
printf("%d ",head->data);
}
void mount_node(int i,int data){
node *tmp;
int digit=0;
int ii=i;
node *p;
if (i==1){
head=(node *)malloc(sizeof(node));
if(!head){
printf("1:malloc error!\n");
return;
}
bzero(head,sizeof(node));
head->data=data;
head->seq=i;
}else{
tmp=(node *)malloc(sizeof(node));
if(!tmp){
printf("2:malloc error!\n");
return;
}
bzero(tmp,sizeof(node));
tmp->data=data;
tmp->seq=i;
while(ii!=1){
push(ii&1);
digit++;
ii>>=1;
}
digit--;
p=head;
while(digit){
if (pop()==1){
p=p->right;
}else{
p=p->left;
}
digit--;
}
if (pop()==1){
p->right=tmp;
}else{
p->left=tmp;
}
}
}
int main(void){
/*待排序目标*/
int data[]={23,45,1,-3,67,100,90,-2,1,1};
/*头节点序号为1,向后依次累加*/
int i=1;
node *tmp;
/*for循环建立堆*/
for(;i<=(sizeof(data)/sizeof(int));i++){
/*产生新节点,挂在完全二叉树上*/
mount_node(i,data[i-1]);
/*每插入一个节点就调整一次堆,此时的调整是从当前节点往上调整*/
adjust_up(i);
}
i--;
/*建好堆后开始输出*/
while(i){
/*由于是从头节点开始输出,每输出一个就就调整一次堆,此时的调整是从头节点往下调整*/
adjust_down(head);
/*将堆中的末尾节点与头节点对调,下一次while循环则为此次变化调整堆*/
tmp=find_node(i,head);
exchange(tmp,head);
/*释放末尾节点*/
free(tmp);
/*将末尾节点对应的父节点指针清空*/
if (i!=1){
if (i&1){
find_node(i/2,head)->right=NULL;
}else{
find_node(i/2,head)->left=NULL;
}
}
i--;
}
printf("\n");
}
运行结果: