堆排序实质就是选择排序的优化版,将选择排序的选择部分优化成logn。
思路:
由小到大堆排序首先要构造大顶堆(父节点的值大于子节点的值)
再依次交换最后一个节点的值,已经排好的不用管
再对第一个结点进行构造大顶堆的操作
重复进行如上操作便排序完成
非递归版本
#include <stdio.h>
#include <stdlib.h>
void swap(int tree[],int a,int b)
{
int temp=tree[a];
tree[a]=tree[b];
tree[b]=temp;
}//交换函数
void heap_sort(int tree[],int n)
{
build_tree(tree,n);
for(int i=n-1;i>=0;i--)//依次从最后一个结点进行交换
{
swap(tree,i,0);
heapify(tree,0,i);//交换完对第一个结点进行重新构造
}
}
void build_tree(int tree[],int n)
{
int lastnode=(n-2)/2;
for(int i=lastnode;i>=0;i--)
{
heapify(tree,i,n);
}//构造大顶堆要从底向上构造
}
void heapify(int tree[],int i,int n)
{
int parent=i;
int child=2*i+1;
while(child<n)
{
if(child+1<n&&tree[child+1]>tree[child])//比较左右孩子,选出大的
{
child++;
}
if(tree[child]>tree[parent])//如果父节点比子节点小就交换
{
swap(tree,child,parent);
parent=child;//改变父节点
}
else//反之退出循环,因为当前结点已经是大顶堆结构了
{
break;
}
child=2*child+1;
}//构造大顶堆
}
int main()
{
int tree[]={97,15,6,5,3,2,9,8,7,16,4,1,23,9,8,4,2,3,5,65};
heap_sort(tree,20);
for(int i=0;i<20;i++)
printf("%d\t",tree[i]);
printf("\n");
return 0;
}
递归版本
#include <stdio.h>
#include <stdlib.h>
void swap(int tree[],int a,int b)
{
int temp=tree[a];
tree[a]=tree[b];
tree[b]=temp;
}//交换函数
void heap_sort(int tree[],int n)
{
build_tree(tree,n);
for(int i=n-1;i>=0;i--)//依次从最后一个结点进行交换
{
swap(tree,i,0);
heapify(tree,0,i);//交换完对第一个结点进行重新构造
}
}
void build_tree(int tree[],int n)
{
int lastnode=(n-2)/2;
for(int i=lastnode;i>=0;i--)
{
heapify(tree,i,n);
}//构造大顶堆要从底向上构造
}
void heapify(int tree[],int i,int n)
{
int l=2*i+1;
int r=2*i+2;
int max=i;
if(l<n&&tree[l]>tree[max])
{
max=l;
}
if(r<n&&tree[r]>tree[max])
{
max=r;
}
//找左右孩子最大值并记录
if(max!=i)//如果左右孩子比父节点大便进行交换并递归
{
swap(tree,max,i);
heapify(tree,max,n);
}
}
int main()
{
int tree[]={97,15,6,5,3,2,9,8,7,16,4,1,23,9,8,4,2,3,5,65};
heap_sort(tree,20);
for(int i=0;i<20;i++)
printf("%d\t",tree[i]);
printf("\n");
return 0;
}
构造小顶堆同理
好好学习天天向上!