二叉堆是近似的完全二叉树
二叉堆的特点是:
(1)父节点永远大于等于(或者小于等于)子节点
(2)每个结点的左子树和右子树又是一个二叉堆(递归)
进行堆排序需要的操作:
(1)堆化:反向调整使每个子叶都是大顶堆或者小顶堆
(2)按序输出元素:把堆顶的最末元素对调,然后调整堆顶元素
完整代码:
#include<stdio.h> void MinHeap(int *A); void MinHeapFixDown(int *A, int i,int n); void sort(int *A,int n); int len(int *A); void swap(int *A, int i, int j); int main() { int A[100]={1,2,5,6,4,3,2,9}; int n=len(A); sort(A,n); for(int i = 0; i< n; i++) { printf("%d",A[i]); } return 0; } //将数组堆化 void MinHeap(int *A) { int n=len(A); for(int i=n/2-1; i>0; i--) { MinHeapFixDown(A,i,n); } } void MinHeapFixDown(int *A, int i,int n)//i记录为当前的结点 { int temp; //先找到左右孩子 int left = 2*i+1;//在i是父节点的情况下,左子节点为2i+1 int right = 2*i+2; //考虑在找左右孩子的时候下标是否越界 if(left>=n) //如果左边都越界了对于二叉堆来说右边肯定也越界了,就直接返回,不进行调整 { return;//其实就是递归的边界 } int min = left; if(right>=n)//如果右孩子越界,那么两个孩子中较小的一定就是左孩子left { min=left; } else { if(A[right]<A[left]) { min=right; } } //以上操作将min指向了左右孩子中较小的那个 //如果A[i]比两个孩子都小则不用调整 if(A[i]<=A[min])//如果当前节点比左右孩子中较小的那个还小,那么就满足小顶堆,不用调整 { return;//不用调整,直接返回 } //否则,找到两个孩子中较小的,和i交换 temp=A[i]; A[i]=A[min]; A[min]=temp; //小孩子那个位置的值发生了变化,i变成小孩子的那个位置(为了再从小孩子那个位置作为结点判断是否满足小顶堆),递归调整 MinHeapFixDown(A, min,n);//再递归调用判断小孩子的位置是否需要调整 } void sort(int *A,int n) { //先对数组A进行堆化 MinHeap(A); for(int x = n-1; x>0; x--)//不断得缩小范围,不断把最后一个减去 { //把堆顶元素和最后 一个元素对调 swap(A,0,x);//交换数组A中的第一个元素和现在剩下的最后一个元素 //缩小堆的范围,对堆顶元素进行向下调整(循环) MinHeapFixDown(A,0,x-1);//对堆顶进行向下调整 } } void swap(int *A, int i, int j) { int temp; temp = A[i]; A[i]=A[j]; A[j]=temp; } int len(int *A) { int i = 0; int sum=0; while(A[i]!=‘\0‘) { sum++; } return sum; }
原文:https://www.cnblogs.com/jessie99/p/12365684.html