数据结构---堆和优先队列

本文介绍了堆的概念,包括最大堆和最小堆,以及二叉堆等不同类型。接着详细讲解了二叉堆的实现,特别是MaxHeap类的设计。此外,还探讨了优先队列,它是一种根据优先级决定出队顺序的特殊队列,常通过堆来实现。最后,讨论了优先队列的应用及其与普通队列的区别。
摘要由CSDN通过智能技术生成

1.01 堆(heap)

是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。

堆的性质

堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全二叉树。

最大堆

将根节点最大的堆叫做最大堆或大根堆。

最小堆

根节点最小的堆叫做最小堆或小根堆。

常见的堆有二叉堆、斐波那契堆等。

堆支持的基本操作:

build:建立一个空堆;
insert:向堆中插入一个新元素;
update:将新元素提升使其符合堆的性质;
get:获取当前堆顶元素的值;
delete:删除堆顶元素;
heapify:使删除堆顶元素的堆再次成为堆。

某些堆实现还支持其他的一些操作,如斐波那契堆支持检查一个堆中是否存在某个元素。

1.02 二叉堆
在这里插入图片描述
在这里插入图片描述
1.03 MaxHeap基于动态数组的最大堆类的定义

  1. 定义类
public class MaxHeap<E extends Comparable<E>>
  1. 定义成员变量
public ArrayList<E> data;
  1. 定义构造函数
public MaxHeap(int capacity){	//自定义堆的大小
	data=new ArrayList<E>(capacity);
}
public maxHeap(){
	data=new ArrayList<>();
}
public MaxHeap(E[] arr){	//自定义堆时 传入一个数组
	data=new ArrayList<E>(arr);
	for(int i=parent(arr.length-1);i>=0;i--){
		siftDown(i);
	}
}
  1. 定义功能(全部通过数组角标操作元素)
//返回堆中的元素个数
public int size(){
	return data.getSize();
}
//堆是否为空
public boolean isEmpty(){
	return data.isEmpty();
}
//用数组表示堆 给定一个点 返回其父亲节点的角标
private int parent(int index){
	if(index==0){
		throw new IllegalArgumentException("node parent");
	}
	return (index-1)/2;
}
//用数组表示堆 给定一个点 返回其左孩子节点的角标
private int leftChild(int index){
	return index*2+1;
}
//用数组表示堆 给定一个点 返回其右孩子结点的角标
private int rightChild(int index){
	return index*2+2;
}
//向堆中添加元素
public void add(E e){
	data.addLast(e);	//元素添加到末尾后 
	siftUp(data.getSize()-1);	//新添加的元素上浮
}
//将新加入的元素上浮
private void siftUp(int k){
	while(k>0&&data.get(parent(k)).compareTo(data.get(k))<0){	//不是根节点并且其父亲节点的值小于当前节点的值
		data.swap(k,parent(k));	//元素交换
		k=parent(k);	//重置要上浮元素的角标
	}
}
//返回堆中的最大值
public E findMax(){
	if(data.isEmpty()){
		throw new IllegalArgumentException("head is null");
	}
	return data.getFirst();
}
//删除堆中的最大值
public E extractMax(){
	E ret=findMax();	//找到最大值
	data.swap(0,data.getSize()-1)	;	//将最大值和数组最后一个元素交换
	data.removeLast();	//删除最后一个元素
	siftDown(0);	//数组第一个元素下沉
	return ret;
}
//将第一个元素下沉
private void siftDown(int k){
	while(leftChild(k)<data.getSize()){	//没到叶子结点
		int j=leftChild(k);
		if(j+1<data.getSize()&&data.get(j+1).compareTo(data.get(j))>0){	//右子树没到叶子结点并且右节点的值大于左节点的值
			j=rigthChild(k);
		}
		if(data.get(k).compareTo(data.get(j))<0){	//要下沉的元素小于左右子树结点中较大的一个时
			data.swap(k,j);	//交换 元素实现下沉
			k=j;	//重置要下沉元素的角标
		}else{	//下沉结束
			break;
		}
	}
}
//去除最大元素后,放入一个新元素
public  E replace(E e){
	E ret=findMax();	//找打最大的元素
	data.set(0,e);	//修改元素
	siftDown(0);	//元素下沉
	return ret;	
}

1.04 优先队列

普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用堆数据结构来实现。
普通队列:先进先出,后进后出
优先队列:出队顺序和入队顺序无关,和优先级相关,本质还是队列

优先队列是0个或多个元素的集合,每个元素都有一个优先权或值。

优先队列的操作:

(1)查找	查找操作用来搜索优先权最小的元素,
(2)插入一个元素
(3)删除
优先权队列中的元素可以有相同的优先权,查找与删除操作可根据任意优先权进行。

应用:

(1)任务管理器中:动态选择优先级最高的任务执行 
(2)游戏中:塔防优先攻击(距离,威胁,先后)

1.04 PriorityQueue基于最大堆实现的优先对列的定义

public class PriorityQueue<E extends Comparable<E>> implements Queue<E>{
	private MaxHeap<E> heap;
	public priorityQueue(){
		heap=new MaxHeap<E>();
	}
	public void enqueue(E e){	//入队
		heap.add(e);	
	}
	public E dequeue(){	//出队
		return heap.extractMax();	//删除堆中最大的元素
	}
	public E getFront(){	//获取对头
		return heap.findMax();
	}
	public int getSize(){	//对的有效长度
		return heap.size();
	}
	public boolean isEmpty(){	//对是否为空
		return heap.isEmpty();
	}
}

对比普通线性结构有何区别?

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值