堆原理与c实现

先明白原理后看实现

一、堆原理

转载自https://www.cnblogs.com/mengdd/archive/2012/11/30/2796845.html

堆排序在最坏的情况下,其时间复杂度也为O(nlogn)

注:

如果根结点是从1开始,则左右孩子结点分别是2i和2i+1。

如果根结点是从0开始,则左右孩子结点分别是2i+1和2i+2,数组是以0开始的,所以一般使用这个!

二、实现与测试

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

/* 堆排序(heap_sort)*/   
 
/* 堆调整,构建大顶堆,arr[]是待调整的数组,i是待调整的数组  
   元素的位置,length是数组的长度 */ 
void heap_adjust(int arr[], int i, int length)  
{  
    int child;  
    int temp;
    
    while (2 * i + 1 < length) {  
        /* 子节点的位置 = 2 * (parent(父结点)) + 1 */ 
        child = 2 * i + 1;  
        /* 得到子结点中较大的结点 */ 
        if(child < length - 1 && arr[child + 1] > arr[child]){  
                child++;  
        }
        /* 如果较大的子结点大于父结点那么把较大的子结点往上移动替换它的父结点 */    
        if(arr[i] < arr[child])  
        {/* 此节点和自己的子节点数据进行交换,就必须进继续比较后代节点*/
            temp = arr[i];  
            arr[i] = arr[child];  
            arr[child] = temp;

            i = child;
        }else {/*没有交换的话 就不对子节点做比较*/  
            break;
        }
    }  
}  
/* 堆排序算法 */ 
void heap_sort(int arr[], int length)  
{  
    int i;  
    /* 调整序列的前半部分元素,调整完之后第一个元素  
       是序列的最大元素,length/2-1是最后一个非叶子结点 */  
    for(i = length/2 - 1; i >= 0; --i) { 
        heap_adjust(arr, i, length);
    }
    
    /* 从最后一个元素开始对序列进行调整,不断的缩小调整  
       的范围直到第一个元素  
       循环里是把第一个元素和当前的最后一个元素交换  
       保证当前的最后一个位置的元素是现在这个序列的最大的  
       不断的缩小调整heap的范围,每一次调整完毕保证第一个  
       元素是当前序列的最大的元素 */  
    for(i = length - 1; i > 0; --i) {  
        arr[i] = arr[0]^arr[i];  /* 交换的一种实现 */
        arr[0] = arr[0]^arr[i];  
        arr[i] = arr[0]^arr[i];  
        heap_adjust(arr, 0, i);      /* 递归调整 */  
    }  
}  
  
int main()  
{  
    int i;  
    int num[] = {98, 48, 777, 63, 57, 433, 23, 1112, 1}; 
    
    printf("sort before : ");
    for(i = 0; i < sizeof(num)/sizeof(int); i++) {  
        printf("%d ", num[i]);  
    }  
    printf("\n");
    
    heap_sort(num, sizeof(num)/sizeof(int));  
    
    printf("sort after  : ");
    for(i = 0; i < sizeof(num)/sizeof(int); i++) {  
        printf("%d ", num[i]);  
    } 
    
    printf("\n");  
    return 0;  
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值