heapsort

/*
 * szlHeapSort.h
 */
#ifndef SZL_HEAP_SORT_H
#define SZL_HEAP_SORT_H

void heapSort(int a[], int n);
void siftDown(int a[], int root, int n);

#endif

/*
 * szlSwap.h
 */
#ifndef SZL_SWAP_H
#define SZL_SWAP_H

//交换两个数
void swap(int *a, int *b);

#endif
/* szlHeapSort.c
 * 堆是其节点值满足一定约束的完全二叉树;
 * 数组实现的n个节点的完全二叉树满足的性质,如果
 * 1.用A[0..n-1]表示这棵树,那么
 * (1)位置i的父节点为(i-1)/2;
 * (2)位置i的孩子节点为2*i+1及2*i+2;
 * (3)第一个叶子节点是n/2;
 * 2.用A[1..n]表示这棵树,那么
 * (1)位置i的父节点为i/2;
 * (2)位置i的孩子节点为2*i及2*i+1;
 * (3)第一个叶子节点是n/2+1;
 */
#include "szlHeapSort.h"
#include "szlSwap.h"
#include "stdio.h"

/*
 * 将具有n个元素的数组a进行堆排序
 */
void heapSort(int a[], int n){
  int i;
  /*
   * 以数组a为输入,建立一个堆
   */
  for(i=(n/2)-1; i>=0; i--){ // 从最后一个内部节点降序地访问到树根节点
    siftDown(a,i,n); // 将每一个节点下沉,建立以位置i为根节点的子堆,sub heap
  }
  
  /*
   * 将树根节点和最后一个叶子节点交换;
   * 并将堆的大小减少1;
   * 然后调整树根,以保持堆序;
   * 循环,直至访问到第2个元素
   */
  for(i=n-1; i>=1; i--){
    swap(&a[0],&a[i]);
    siftDown(a,0,i);
  }
}

/*
 * 将root位置的节点在大小为n的堆a中调整,以保持堆序
 */
void siftDown(int a[], int root, int n){
  int done, maxChild;

  done = 0;
  while(!done){
    
	if(root*2+2<=n-1){ //如果root存在左孩子和右孩子
	  if(a[root*2+1]>a[root*2+2]){ //max记住较大的孩子
        maxChild=root*2+1;
	  }
	  else{
	    maxChild=root*2+2;
	  } 
	}
	else if(root*2+1==n-1){ // 如果root有左孩子
	  maxChild=root*2+1;
	}
	else{ //没有孩子节点
	  maxChild = root; // 标记root为最大的元素
	}
	
	if(a[root] < a[maxChild] ){ // 将最大的元素和root位置的元素交换
      swap(&a[maxChild],&a[root]);
	  root=maxChild; //以较大的孩子为根节点继续往下访问
    }
	else{
	  done=1;
	}
  }	
}


 

/*
 * szlSwap.c
 */
#include "szlSwap.h"

void swap(int *a, int *b){
	int t=*a;
	*a=*b;
	*b=t;
}


 更为简洁的版本:

/*
 * heapsort.c
 */
#include <stdio.h>
#define N 30

void swap (int * p, int * q){
    if (! (p == q)){
        * p ^= * q;
        * q ^= * p;
        * p ^= * q;
    }
}

void sift_down (int a[], int i, int n){
    int max = i;
    if ( 2*i+2 <= n-1){
        max = a[2*i+1] > a[2*i+2] ? (2*i+1) : (2*i+2);
    }
    else if (2*i+1 == n-1){
        max = 2*i+1;
    }
    if (a[max] > a[i]){
        swap (&a[i], &a[max]);
        sift_down (a, max, n); /* recursion */
    }
}

void build_heap (int a[], int n){
    int i;
    for (i=(n-1)/2; i>=0; i--){
        sift_down (a, i, n);
    }
}

void heapsort (int a[], int n){
    int i;
    build_heap (a, n);
    for (i=n-1; i>0; i--){
        swap (&a[0], &a[i]);
        sift_down (a, 0, i);
    }
}

int main (int argc, char ** argv){
    int n;
    int i;
    int a[N];
#ifdef DEBUG1
    freopen ("in.txt", "r", stdin);
#endif
    scanf ("%d", &n);
    for (i=0; i<n; i++)
        scanf ("%d", &a[i]);

    heapsort (a, n);

    for (i=0; i<n; i++)
        printf ("%d ", a[i]);
    
#ifdef DEBUG1
    fclose (stdin);
#endif
    return 0;
}





 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值