1,堆实际就是一个二叉树,满足两个个特点
- 为完全二叉树
- 父节点的值大于两个孩子的值
2,算法思想
- 建立树,以一个数组建立树
data=new T[n+1];
for(int i=0;i<n;i++){
data[i+1] =array[i];
}
count=n;
for(int i=count/2;i>=1;i--){
shiftDown(i);
}
n/2为第一个不是叶子节点的值,我们保证每一个非叶子节点为一个堆,那么这就是一个堆
shiftDown在后面
- 插入
void insert(T value){
data[count+1]=value;
count++;
shiftUp(count);//简单的添加到堆中,再进行比较保证还是一个堆
}
void shiftUp(int count){//保持堆的有序性
while(data[count/2]<data[count] && count/2>=1){
swap(data[count/2],data[count]);
count=count/2;
}
}
//插入的值作为最后一个,从底到根节点,将它和它的父节点比较,保证父节点大于子节点。
- 取出
T extractMax(){
T ret= data[1];
swap(data[1],data[count]);
count--;
shiftDown(1);
return ret;
}
//我们之后取出第一个值,即为最大值。
//进行排序,就是生成堆,每次取出最大值,就进行了排序
//我们讲第一个取出,将最后一个放到第一个,然后进行比较交换,保证取出后还是堆
void shiftDown(int k){
int value=data[k];
while(2*k<=count){
int j=2*k;
if(j+1<=count&&data[j+1]>data[j]){
j++;
}//比较左孩子和右孩子的值,获得最大的一个
if(value>=data[j]){
break;
}//如果节点的值大于孩子的最大值,那么这就是该放置的位置,退出循环
data[k]=data[j];
//如果孩子最大值大于父节点,那么将这最大的一个和父节点交换,继续往下比较
k=j;
}
data[k]=value;
}
总结,堆排序就是对一个堆不断的取值,每次取出都是剩下的最大值,就进行了排序。
时间复杂的O(nlogn)