数据结构-堆的实现

堆本质是一棵二叉树,其中所有的元素都可以按全序语义进行比较。用 堆来进行存储需要符合以下规则:

1.元素可比较性:数据集中的元素可以进行比较,就是要实现Comparable接口;。

2.节点最大/最小性:每个节点的元素必须大于或小于该节点的孩子节点的元素;

3.堆是一棵完全二叉树。

堆有两种:最大堆和最小堆。

最小堆中每个节点的优先级小于或者等于它的子节点;最大堆则相反,每个节点的优先级都大于或者等于它的子节点。

如下图:

本文只着重讲最大堆吧,最小堆是一样的。

堆的大小是提前知道的,在java集合中堆是通过ArrayList数组实现的:

1.根节点位置:根节点的数据总是在数组的位置[0]

2.节点的父节点位置:假设一个非根节点的数据在数组中的位置[i],那么它的父节点总是在位置[(i-1)/2]

3.节点的孩子节点位置:假设一个节点的数据在数组中的位置为[i],那么它的孩子(如果有)总是在下面的这两个位置:左孩子在[2*i+1],右孩子在[2*i+2]

在堆中主要是插入和删除节点的操作,这两种操作无论是哪一种,完成之后都还是一个堆,操作时要进行堆的调整,使其是个新堆。

一,添加一个新节点:(不断地和父节点比较)

插入的思路是这样的:当插入一个元素时,先将这个元素插入到队列尾,然后将这个新插入的元素和它的父节点进行优先权的比较,如果比父节点的优先权要大,则和父节点呼唤位置,然后再和新的父节比较,直到比新的父节点优先权小为止

二,删除一个节点(不断比较左右孩子节点大小,大的上移)

从堆中删除优先权最大的元素的思路是将队列尾的元素值赋给根节点,队列为赋 值为null。然后检查新的根节点的元素优先权是否比左右子节点的元素的优先权大,如果 比左右子节点的元素的优先权小,就交换位置,重复这个过程,直到秩序正常。

heap.java实现

//最大堆
import java.util.ArrayList;
public class Heap<E extends Comparable>{
	private ArrayList<E> list=new ArrayList<E>();//用数组实现堆

    public Heap(){}
    public Heap(E[] objects){
    	for(int i=0;i<objects.length;i++){
    		add(objects[i]);
    	}
    }

    public void add(E newObject){//添加一个元素
    	list.add(newObject);
    	int currentIndex=list.size()-1;

    	while(currentIndex>0){
    		int parentIndex=(currentIndex-1)/2;//找到该结点的父结点
    		if(list.get(currentIndex).compareTo(list.get(parentIndex))>0){//与父节点比较
    			//如果当前结点的值大于父结点就交换位置
    			E temp=list.get(currentIndex);
    			list.set(currentIndex, list.get(parentIndex));
    			list.set(parentIndex, temp);
    		}
    		else
    			break;
    		currentIndex=parentIndex;
    	}
    }

    public E remove(){//删除并返回根结点,堆的特点是移除了根结点后还是堆
    	if(list.size()==0) return null;

    	E removeObject=list.get(0);
    	list.set(0, list.get(list.size()-1));//把最后一个结点放在根结点的位置
    	list.remove(list.size()-1);

    	int currentIndex=0;
    	while(currentIndex<list.size()){
    		int leftChildIndex=2*currentIndex+1;
    		int rightChildIndex=2*currentIndex+2;//左右孩子结点的坐标

    		if(leftChildIndex>=list.size())break;
    		//比较左右孩子的值,使maxIndex指向值大的结点
    		 int maxIndex=leftChildIndex;
    		 if(rightChildIndex<list.size()){
    			 if(list.get(maxIndex).compareTo(list.get(rightChildIndex))<0){
    				 maxIndex=rightChildIndex;
    			 }
    		 }
    		 //如果当前结点的值小于其左右孩子中的大的值,就交换两个结点
    		 if(list.get(currentIndex).compareTo(list.get(maxIndex))<0){
    	          E temp=list.get(maxIndex);
    	          list.set(maxIndex, list.get(currentIndex));
    	          list.set(currentIndex, temp);
    	          currentIndex=maxIndex;
    	    	}
    		 else
    			 break;
    	}

    	return removeObject;   	

    }

    public int getSize(){
    	return list.size();
    }

}
时间: 2025-01-08 16:11:34

数据结构-堆的实现的相关文章

基本数据结构——堆(Heap)的基本概念及其操作

基本数据结构――堆的基本概念及其操作 小广告:福建安溪一中在线评测系统 Online Judge 在我刚听到堆这个名词的时候,我认为它是一堆东西的集合... 但其实吧它是利用完全二叉树的结构来维护一组数据,然后进行相关操作,一般的操作进行一次的时间复杂度在 O(1)~O(logn)之间. 可谓是相当的引领时尚潮流啊(我不信学信息学的你看到log和1的时间复杂度不会激动一下下)!. 什么是完全二叉树呢?别急着去百度啊,要百度我帮你百度: 若设二叉树的深度为h,除第 h 层外,其它各层 (1-h-1

数据结构--堆的实现之深入分析

一,介绍 以前在学习堆时,写了两篇文章:数据结构--堆的实现(上)   和   数据结构--堆的实现(下),  感觉对堆的认识还是不够.本文主要分析数据结构 堆(讨论小顶堆)的基本操作的一些细节,比如 insert(插入)操作 和 deleteMin(删除堆顶元素)操作的实现细节.分析建堆的时间复杂度.堆的优缺点及二叉堆的不足. 二,堆的实现分析 堆的物理存储结构是一维数组,逻辑存储结构是完全二叉树.堆的基本操作有:insert--向堆中插入一个元素:deleteMin--删除堆顶元素 故堆的类

【C/C++学院】0828-STL入门与简介/STL容器概念/容器迭代器仿函数算法STL概念例子/栈队列双端队列优先队列/数据结构堆的概念/红黑树容器

STL入门与简介 #include<iostream> #include <vector>//容器 #include<array>//数组 #include <algorithm>//算法 using namespace std; //实现一个类模板,专门实现打印的功能 template<class T> //类模板实现了方法 class myvectorprint { public: void operator ()(const T &

数据结构--堆的实现(下)

1,堆作为优先级队列的应用 对于普通队列而言,具有的性质为FIFO,只要实现在队头删除元素,在队尾插入元素即可.因此,这种队列的优先级可视为按 时间到达 的顺序来衡量优先级的.到达得越早,优先级越高,就优先出队列被调度. 更一般地,很多应用不能单纯地按时间的先后来分优先级,比如按CPU占用时间或者其它方式……在这种情形下,使用堆更容易表达优先级队列. 2,堆的两个性质:①结构性质--堆从结构上看是一颗完全二叉树.然而,从物理存储上看,堆的实现基本上是使用一个一维数组存储堆中所有的结点.②orde

C 数据结构堆

引言 - 数据结构堆 堆结构都很耳熟, 从堆排序到优先级队列, 我们总会看见它的身影. 相关的资料太多了, 堆 - https://zh.wikipedia.org/wiki/%E5%A0%86%E7%A9%8D 无数漂亮的图片接二连三, 但目前没搜到一个工程中可以舒服用的代码库. 本文由此痛点而来. 写一篇奇妙数据结构堆的终结代码. 耳熟终究比不过手热 ->--- 对于 heap 接口思考, 我是这样设计 #ifndef _H_HEAP #define _H_HEAP // // cmp_f

数据结构-堆

堆(英语:Heap),是一种拥有像树那样的特殊数据结构,或者理解为具有优先级的树.它的特点是父节点的值大于(或小于)两个子节点的值(分别称为大顶堆和小顶堆).它常用于管理算法执行过程中的信息,应用场景包括堆排序,优先队列等.堆通常是一个可以被看做一棵树的数组(或ArrayList)对象.常见的堆有二叉堆.二项堆.斐波那契堆等. 二叉堆(Binary heap) 二叉堆是一种特殊的堆,实为二叉树的一种:是完全二叉树或者是近似完全二叉树.二叉堆满足堆特性:父节点的键值总是保持固定的序关系于任何一个子

浅谈数据结构-堆

在数据结构的世界中有一个叫堆的玩意,这玩意有什么用呢?无用,都去pq了 堆,其实就是一棵完全二叉树. “若设二叉树的深度为h,除第 h 层外,其它各层 (1-h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树”  by 谋财害命公司 百度 ↑清真的 完全二叉树 ↓ 啊那么为什么会闲的无聊出现这种奇怪的数据结构呢? 因为我们的某些算法可能需要堆来进行优化,如dj,prim. 堆可以在O(1)的时间取出最优值,但是需要O(logn)的时间修改和O(nlogn)

数据结构—堆

堆是二叉树中的一种,是一种常见的数据结构,具有以下性质: 任意节点小于(最小堆)或大于(最大堆)它的所有后裔,最小元或最大元在堆的根上(堆序性). 堆总是一棵完全二叉树 最大堆如图一,最小堆如图二. 最小堆的实现如下: MinHeap.h 1 #include "stdafx.h" 2 #include <iostream> 3 using namespace std; 4 template <typename Type> 5 class MinHeap{ 6

数据结构-----堆的基本操作和应用

(一)用仿函数实现大堆小堆 堆数据结构是一种数组对象,它可以被视为一棵完全二叉树结构. 堆结构的二叉树存储是 最大堆:每个父节点的都大于孩子节点. 最小堆:每个父节点的都小于孩子节点. 仿函数(functor),就是使一个类的使用看上去象一个函数.其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了.在实现大,小堆的过程中,有些功能的的代码,会在不同的成员函数中用到,想复用这些代码,有两种途径. 1)公共的函数,这是一个解决方法,不过函数用到的一些变量,就可

数据结构——堆(Heap)大根堆、小根堆

Heap是一种数据结构具有以下的特点: 1)完全二叉树: 2)heap中存储的值是偏序: Min-heap: 父节点的值小于或等于子节点的值: Max-heap: 父节点的值大于或等于子节点的值: 堆的存储: 一般都用数组来表示堆,i结点的父结点下标就为(i–1)/2.它的左右子结点下标分别为2 * i + 1和2 * i + 2.如第0个结点左右子结点下标分别为1和2. 堆的操作:insert 插入一个元素:新元素被加入到heap的末尾,然后更新树以恢复堆的次序. 每次插入都是将新数据放在数组