堆排序

堆排序

算法思想:

1.堆排序应用了最小(大)堆的根节点是最小(大)值这一特性。
2.每次取出根结点的最值,再将最右边的叶结点放到根结点的位置。
3.基于第二步,向下调整根结点的元素,直到变成一个新的最小(大)堆。

#include <stdio.h>
#include <stdlib.h>

typedef struct{

    int data[1001];
    int length;
}Heap;//堆的数据类型

void Swap(int *a,int *b);//交换
Heap *Init_heap(int length);//将heap数组初始化成堆
void Down(Heap *h,int i);//将第i号结点向下调整
void Heapsort(Heap *h,int data[]);//堆排序 

int main(void){

    int n;
    int data[1001];

    printf("请输入元素个数:");
    scanf("%d",&n);
    Heap *h=Init_heap(n);
    Heapsort(h,data);

    for(int i=0;i<n;++i)
        printf("%3d",data[i]);


    return 0;
}

void Swap(int *a,int *b){

    int t;
    t=*a;
    *a=*b;
    *b=t;
    return ;
}

Heap *Init_heap(int length){

    Heap *h=(Heap *)malloc(sizeof(Heap));
    h->length=length;
    printf("请输入%d个数:",length);
    for(int i=1;i<h->length+1;++i)
        scanf("%d",h->data+i);

    /****生成最小堆*****/
    //从后向前遍历,找父节点,若比父节点小,则交换
    for(int i=length;i>1;--i){

        if(h->data[i]<h->data[i/2]) 
            Swap(h->data+i,h->data+i/2);
    }

    return h;
}

void Down(Heap *h,int i){

    int flag;//flag用来记录是否发生了交换
    while(i*2<h->length+1){//存在左子结点 
        //将flag置为1
        flag=1;
        if(i*2+1<h->length+1){//存在右子结点 

            if(h->data[i]>h->data[i*2+1] && h->data[i*2]<h->data[i*2+1]){

                Swap(h->data+i,h->data+i*2);
                i*=2;
                flag=0;
            }
            else if(h->data[i]>h->data[i*2] && h->data[i*2+1]<h->data[i*2]){

                Swap(h->data+i,h->data+i*2+1);
                i=i*2+1;
                flag=0;
            }
        }
        else if(h->data[i*2]<h->data[i]){

            Swap(h->data+i*2,h->data+i);
            i*=2;
            flag=0;
        }
        if(flag)//没有发生交换,说明调整完成
            break;
    }   
    return ;
}

void Heapsort(Heap *h,int data[]){

    int i=0;
    while(h->length){//当堆的结点个数变成0,则排序完成

        //将根结点弹出
        data[i++]=h->data[1];
        //将最右边的叶结点放到根结点的位置
        h->data[1]=h->data[h->length--];
        //向下调整
        Down(h,1);
    }

    return ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值