数据结构——堆

数据结构堆

1.定义:

一类由完全二叉树组成的数组对象的数据结构。

2.特点:

①它是完全二叉树,除了树的最后一层结点无需点满,其他层数必须都是满的,如果最后一层不满,则必须要求左满右不满。
②该数据结构底层由数组实现。

3.图解:

在这里插入图片描述

4.规律:

①若一个索引为k,则父结点索引为k/2,子结点位置为2k或者2k+1。
②向上一层,则k = k/2;向下一层,则k = 2k或者k = 2k+1。
③每个结点都大于它的子结点。

5.堆的设计框架

在这里插入图片描述

6.代码实现

(1).属性

	//数组储存T类型元素
    private T[] items;
    //堆的元素个数
    private int N;

(2).构造方法

	//构造方法
    public Heap(int capacity) {
        items = (T[]) new Comparable[capacity];
        N = 0;
    }

(3).功能方法

<1>.判断索引i处的元素是否小于索引j处元素
	//判断索引i处的元素是否小于j处元素
    public boolean less(int i, int j) {
        return items[i].compareTo(items[j]) < 0;
    }
<2>.交换索引i和索引j处元素
	//交换索引i处与索引j处的元素
    public void exchange(int i,int j){
        T temp = items[i];
        items[i] = items[j];
        items[j] = temp;
    }
<3>.向堆中插入元素t
	//向堆中插入一个元素
    public void insert(T t){
        //在数组长度+1的位置添加,并且个数N+1
        items[++N] = t;
        //调用上浮算法,使k处元素处在正确位置
        swim(N);
    }
<4>.上浮算法
	//上浮算法
    public void swim(int k){
    
        while(k>1){
		//使索引为k的元素与父结点进行比较
		//若前者较小,则结束循环
		//若后者较小,则交换其位置
            if (less(k,k/2)){
                break;
            }
            exchange(k,k/2);
            //更新新的k值
            k = k/2;
        }
    }
<5>.删除堆中最大的元素,并返回该元素
	//删除堆中最大元素,并返回
    public T deleteMax(){
        //用新变量记录原最大值,便于函数的返回值
        T max = items[1];
        //由于根结点最大,交换根结点与尾结点的元素
        exchange(1,N);
        //删除尾结点的元素
        items[N] = null;
        //使用下沉算法使新的根结点处于适合的位置
        sink(1);
        //元素个数-1
        N--;
        //返回删除的元素值
        return max;
    }
<6>.下沉算法
	//下沉算法
    public void sink(int k){
      
        while (k*2 <= N){
            //考虑子结点有左右结点的情况
            //设置变量储存左右子结点的较大值索引
            int bigIndex ;
            if (k*2+1 <= N){
                if (less(k*2,k*2+1)){
                    bigIndex = k*2+1;
                }else{
                    bigIndex = k*2;
                }
            }
            //子结点仅有左节点情况
            else{
                bigIndex = k*2;
            }
            if (less(bigIndex,k)){
                break;
            }
            exchange(bigIndex,k);
            //变换k的值
            k = bigIndex;
        }
    }

7.堆的应用

(1).堆排序

<1>.设计框架

在这里插入图片描述

<2>.代码实现
a.判断heap堆中索引i处元素是否小于索引j处元素
	//判断Heap堆中元素索引i处元素是否小于索引j处的元素
    private static boolean less(Comparable[] heap,int i,int j){
        return heap[i].compareTo(heap[j])<0;
    }
b.交换heap堆中索引i处元素与索引j处元素
	//交换堆中索引i与索引j处的元素
    private static void exchange(Comparable[] heap,int i,int j){
        Comparable temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }
c.根据待排序数组source,构造出堆heap
	//根据原数组source,构建出堆heap
    private static void createHeap(Comparable[] source,Comparable[] heap){
        //调用System下的ArrayCopy方法将source数组拷贝到heap数组中形成无序堆
        System.arraycopy(source,0,heap,1,source.length);
        //对新的无序堆中元素进行循环下沉操作(从数组长度一半开始,向1扫描),使其有序
        for (int i = heap.length/2;i > 0;i--){
            sink(heap,i,heap.length-1);
        }
    }
d.对source数组中元素从小到大排序
	//对source中的元素从小到大排序
    public static void sort(Comparable[] source){
        //构建堆
        Comparable[] heap = new Comparable[source.length+1];
        createHeap(source,heap);
        //定义一个变量,记录未排序数组中的最大索引
        int N = heap.length-1;

        while(N != 1){
            //交换索引1处的元素与未排序的最大索引处元素
            exchange(heap,1,N);
            //变换N的值,使其不在参与下一轮排序
            N--;
            //下沉算法,使索引1处的新元素就位
            sink(heap,1,N);
        }
        //将heap中的元素拷贝到原数组source中即排序成功
        System.arraycopy(heap,1,source,0,source.length);
    }
e.在堆heap中,在0-range范围内堆target结点做下沉算法
	//在heap中,对target下沉算法,范围是0-range
    private static void sink(Comparable[] heap,int target,int range){
        while(target*2<=range){
            //当左右结点都存在的时候,找出元素最大值对应下标
            int bigIndex;
            if (target*2+1<=range){
                //比较左右结点元素大小
                if (less(heap,target*2,target*2+1)){
                    bigIndex = target*2+1;
                }else{
                    bigIndex = target*2;
                }
            }
            //当仅存在左结点时
            else{
                bigIndex = target*2;
            }
            //比较目标节点target与找到的子结点较大值
            if (!less(heap,target,bigIndex)){
                break;
            }
            //当target比子结点小时,交换元素
            exchange(heap,target,bigIndex);

            //变换target的值
            target = bigIndex;
        }
    }
f.堆排序的测试
public class HeapSortTest {
    public static void main(String[] args) {
        //创建一个字符串数组sortexample
        String[] str = {"S","O","R","T","E","X","A","M","P","L","E"};
        //调用写好的堆排序方法
        HeapSort.sort(str);
        //打印输出结果
        System.out.print(Arrays.toString(str));
    }
}

输出结果:

[A, E, E, L, M, O, P, R, S, T, X]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值