(第17讲)堆的数组实现

堆:

1、实际是一种完全二叉树,只有最后一层会不满,所以用数组实现,数组都会填满,不会有空缺

2、堆的左右子节点都不大于父节点,即父节点大于或者等于其子节点

程序如下:

/**
 * 堆:基于数组的
 * 堆实际上是一个完全二叉树,并且其左右子节点都不大于父节点(父节点大于子节点)
 */
package com.twelve;


import java.util.Scanner;


public class HeapApp {


public static void main(String[] args) {
int size = 32;
Heap  heap = new Heap(size);
heap.insert(70);            
heap.insert(40);
heap.insert(50);
heap.insert(20);
heap.insert(60);
heap.insert(100);
heap.insert(80);
heap.insert(30);
heap.insert(10);
heap.insert(90);  heap.display();
heap.insert(53); heap.display();
heap.delete();
heap.display();
     System.out.println("请输入两个整数");
     int index = getInt();
     int value = getInt();
     heap.change(index, value);
     heap.display();
}
public static String getString(){
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
return s;
}
public static int getInt(){
String s = getString();
return Integer.parseInt(s);
}
}
//结点类
class Node{
private int data;
public int getData(){
return data;
}
public void setData(int value){
data = value;
}
public Node(int data){
this.data = data;
}
}
//堆类
class Heap{
private Node[] heapArr ;
private int curlen;
private int arrlen;
public Heap(int size){
arrlen = size;
heapArr = new Node[arrlen];
curlen = 0;
}
//增
public void insert(int key){
if(!isFull()){
Node newnode = new Node(key);
heapArr[curlen] = newnode;
trickleUp(curlen);
curlen++;
}

}
//删:删除根节点上的,在本案例中是降序堆,所以是删除优先级最大的
public void delete(){
heapArr[0] = heapArr[--curlen];
trickleDown(0);
}
//更改优先级
public void change(int index,int value){
int oldvalue = heapArr[index].getData();
heapArr[index].setData(value);
if(oldvalue<value)
trickleUp(index);
else 
trickleDown(index);
}
//向上筛选
public void trickleUp(int index)
{
int parent = (index-1)/2;
Node temp = heapArr[index];
while(index>0 && heapArr[parent].getData()<temp.getData())
{
heapArr[index] = heapArr[parent];
index = parent;
parent = (parent-1)/2;
}
heapArr[index] = temp;
}
//向下筛选
public void trickleDown(int index){
Node temp = heapArr[index];
while(index < curlen/2){//当这个位置有子节点的时候
int left = index*2+1;
int right = left+1;
int larger = 0;
if(right<curlen && heapArr[left].getData()<heapArr[right].getData())
larger = right;
else
larger = left;
heapArr[index] = heapArr[larger];
index = larger;
}
heapArr[index] = temp;
}
//遍历
public void display(){
System.out.println("数组显示");
for(int i=0;i<arrlen;i++){
if(heapArr[i]!=null){
//因为没有洞,堆是一颗完全二叉树,所以不用判断这个位置上的结点是否有值,直接显示即可
System.out.print(heapArr[i].getData()+" ");
}else
System.out.print(" ");
}
System.out.println();
String dot = ".......................................";
System.out.println(dot+dot);
int nBlanks = 32;//空格的长度
   int itemsPerRow = 1;//一行
   int column = 0;//一行中的第一个元素
   int j = 0;    //堆中元素的下标        
 //当堆中有元素时
   while(curlen > 0)     
      {
      if(column == 0)                  // 一行中的第一个元素
         for(int k=0; k<nBlanks; k++)  //前面的空白
            System.out.print(' ');  
     System.out.print(heapArr[j].getData());//输出堆中的元素
      
      if(++j == curlen) //如果堆中元素输出完毕,结束       
         break;  
      if(++column==itemsPerRow)        // 一行结束
         {
         nBlanks /= 2;                 // 一半的 空格
         itemsPerRow *= 2;             // 两倍的项数
         column = 0;                   // 从新开始
         System.out.println();         //  新的一行
         }
      else                             
         for(int k=0; k<nBlanks*2-2; k++)
            System.out.print(' ');     // 中间的空格
      }//while循环结束,即堆中元素输出完毕  
System.out.println("\n"+dot+dot);
}
//判断是否为空
public boolean isEmpty(){
return curlen==0;
}
//判断是否为满
public boolean isFull(){
return curlen==arrlen;

}

结果是:

 数组显示
100 90 80 30 60 50 70 20 10 40                       
..............................................................................
                                100
                90                              80
        30              60              50              70
    20      10      40
..............................................................................
数组显示
100 90 80 30 60 50 70 20 10 40 53                      
..............................................................................
                                100
                90                              80
        30              60              50              70
    20      10      40      53
..............................................................................
数组显示
90 60 80 30 40 50 70 20 10 53 53                      
..............................................................................
                                90
                60                              80
        30              40              50              70
    20      10      53
..............................................................................
请输入两个整数
3
98
数组显示
98 90 80 60 40 50 70 20 10 53 53                      
..............................................................................
                                98
                90                              80
        60              40              50              70
    20      10      53
..............................................................................

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值