堆
堆中某个结点的值总是不大于或者不小于其父结点的值
堆总是一个完全二叉树
堆排序
如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储
在一个一维数组中,并满足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为
小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
//堆排序 :
//时间复杂度:(nlog2n)
//空间复杂度:O(1)
//不稳定
接口:
package f.DS.Tree;
interface Heap {
//初始化建立大根堆
public void initHeap(int[] array);
//向上调整,从孩子节点开始调整
void AdjustDown(int child,int len);
void AdjustUp(int child);
// 插入 item 到堆中
void pushHeap(int item);
// 返回堆顶元素,删除数据元素
int popHeap();
// 返回堆顶元素,不删除数据元素
int getHeapTop();
//堆排序
void HeapSort();
//打印堆
void show();
}
方法:
package f.DS.Tree;
import java.util.Arrays;
public class TestHeap implements Heap{
private int[] elem;//定义数组elem[]
private int usedSize;//定义数组的有效长度
private static final int DEFAULT_SIZE=10;//定义常量DEFAULT_SIZE
public TestHeap(){
this.elem=new int[DEFAULT_SIZE];//初始化elem[]
this.usedSize=0;
}
// 创建一个大根堆
@Override
public void initHeap(int[] array) {
for (int i=0;i<array.length;i++){
this.elem[i]=array[i];
this.usedSize++;
}
for(int i=(array.length-1-1)/2;i>0;i--){//最后一棵字数的父亲结点(array.length-1-1)/2
AdjustDown(i,this.usedSize);//每棵树向下调整 整棵树从下往上调整
}
}
//判断是否为满
public boolean isFull(){
return this.usedSize==this.elem.length;
}
//每棵树向下调整 整棵树从下往上调整
@Override
public void AdjustDown(int root, int len) {
int parent=root;//定义父节点
int child=2*parent+1;//定义孩子结点
while (child<len){
if(child+1<len&&elem[child]<elem[child+1]){
++child;
}
//child下标存放左右孩子最大值
if(elem[child]>elem[parent]){
//交换
int tmp=elem[child];
elem[child]=elem[parent];
elem[parent]=tmp;
parent=child;
child=2*parent+1;
}else{
break;
}
}
}
@Override
public void AdjustUp(int child) {
int parent = (child-1)/2;
while (child>0){
if(elem[child]>elem[parent]){
int tmp=elem[child];
elem[child]=elem[parent];
elem[parent]=tmp;
child=parent;
parent=(child-1)/2;
}else{
break;
}
}//child==0时退出循环 大根堆排序结束
}
// 插入 item 到堆中
@Override
public void pushHeap(int item) {
if(isFull()){
this.elem=Arrays.copyOf(this.elem,2*this.elem.length);
}
this.elem[this.usedSize]=item;
this.usedSize++;
AdjustUp(this.usedSize-1);
}
public boolean isAmpty(){
return this.usedSize==0;
}
// 返回堆顶元素,删除数据元素
@Override
public int popHeap() {
if (isAmpty()) {
throw new UnsupportedOperationException("堆为空");
}
int oldData=elem[0];
int tmp = elem[0];
elem[0] = elem[this.usedSize-1];
elem[this.usedSize-1] = tmp;
this.usedSize--;
AdjustDown(0, this.usedSize );//向下调整为大根堆
return oldData;
}
// 返回堆顶元素,不删除数据元素
@Override
public int getHeapTop() {
if (isAmpty()) {
throw new UnsupportedOperationException("堆为空");
}
return elem[0];
}
//堆排序
@Override
public void HeapSort() {
int end=this.usedSize-1;
while (end>0){
int tmp = elem[0];
elem[0] = elem[end];
elem[end] = tmp;
AdjustDown(0,end);
end--;//调整后 再调整下标的前一个
}
}
//打印堆
@Override
public void show() {
for(int i=0;i<this.usedSize;i++){
System.out.print(elem[i]+" ");
}
System.out.println(" ");
}
public static void main(String[] args) {
TestHeap testHeap=new TestHeap();
int[] array={0,1,2,3,4,5,6,7,8,9};
testHeap.initHeap(array);
testHeap.show();
testHeap.HeapSort();
testHeap.show();
}
}
//
输出结果: