数据结构_二叉树Ⅲ——堆与优先队列

堆(Heap)



堆是一种完全二叉树,只是是用数组的形式表示二叉树而已

它其实是利用完全二叉树的结构来维护一组数据

例如这样一棵完全二叉树:

它用堆的形式表现就是这样的:

当然,一般的堆每个元素都是数字呢(不然小根堆与大根堆就没办法实现了呢)

大根堆与小根堆

顾名思义,大根堆/小根堆就是保证根节点是所有数据中最大/小,并且尽力让小的节点在上方

例如下面这个二叉树就是一个小根堆呢

(借鉴某书图片)

那如何将任意一个堆调整至大根堆/小根堆呢?

  1. 从上向下调整

    让当前结点与它的左右孩子进行比较,哪个比较小就和它交换,更新询问节点的下标为被交换的孩子节点下标,否则退出。

    void heapdown(int i) //传入一个需要向下调整的结点编号i
    {
       int t,flag=0;//flag用来标记是否需要继续向下调整
       //当i结点有儿子的时候(其实是至少有左儿子的情况下)并且有需要继续调整的时候循环需执行
       while(i*2<=n&&flag==0)
       {
           //首先判断他和他左儿子的关系,并用t记录值较小的结点编号
           if(h[i]>h[i*2])
               t=i*2;
           else t=i;
           //如果他有右儿子的情况下,再对右儿子进行讨论
           if(i*2+1<=n)
           {
               //如果右儿子的值更小,更新较小的结点编号
               if(h[t]>h[ i*2+1])
                   t=i*2+1;
           }
           //如果发现最小的结点编号不是自己,说明子结点中有比父结点更小的
           if(t!=i)
           {
               swap(t,i);
               i=t;//更新i为刚才与它交换的儿子结点的编号,便于接下来继续向下调整
           }
           else flag=1;//则否说明当前的父结点已经比两个子结点都要小了,不需要在进行调整了
       }
       return;
    }
  2. 从下向上调整

    让当前结点和它的父亲节点比较,若比父亲节点小就交换,然后将当前询问的节点下标更新为原父亲节点下标,否则退出。 

    void heapup(int i) //传入一个需要向上调整的结点编号i
    {
       int flag=0; //用来标记是否需要继续向上调整
       if(i==1)  return; //如果是堆顶,就返回,不需要调整了
       while(i!=1&&flag==0)
       {
           //判断是否比父结点的小
           if(h[i]<h[i/2])
               swap(i,i/2);//交换他和他爸爸的位置
           else flag=1;//表示已经不需要调整了,当前结点的值比父结点的值要大
           i=i/2; //这句话很重要,更新编号i为它父结点的编号,从而便于下一次继续向上调整
       }
       return;
    }

优先队列



优先队列其实是在普通队列的基础上增加了每个元素的优先性(值)

众所周知,普通队列是遵循元素先进先出的原则,进队只能从前面进,出队只能出最后一个

而优先队列不再遵循先入先出的原则,而是分为两种情况:

最大优先队列,无论入队顺序,当前最大的元素优先出队。

最小优先队列,无论入队顺序,当前最小的元素优先出队。

例如说下面的这个优先队列出队就需要出8这个元素

但这种算法的时间复杂度并不理想

如果只用线性数据结构的话,入队和出队的时间复杂度都是O(n)

但我们如果通过二叉堆的方式,每次上浮最大的或最小的

这时出队和入队操作都只需要O(logn)的时间复杂度了

但从来不用STL的本蒟蒻只能用结构体而不会queue的操作QAQ

原文地址:https://www.cnblogs.com/shengzhe/p/10352669.html

时间: 2024-10-27 17:42:39

数据结构_二叉树Ⅲ——堆与优先队列的相关文章

数据结构之基于堆的优先队列

优先队列的最重要的操作:删除最大元素(或最小)和插入元素.数据结构二叉堆能够很好的实现队列的基本操作.二叉堆的结点按照层级顺序放入数组,用长度为N+1的私有数组pq来表示一个大小为N的堆(堆元素放在pq[1]至pq[N]之间,为方便计数,未使用pq[0]),跟节点在位置1,它的子结点在位置2和3,以此类推.位置k的节点的父节点位置为k/2,它的两个子节点位置分别为2k和2k+1.当一颗二叉树的每个节点都大于等于它的两个子节点时,称为大根堆.当一颗二叉树的每个节点都小于等于它的两个子节点时,称为小

数据结构 # 二叉树/堆/栈

数据结构是计算机存储.组织数据的方式.数据结构是指相互之间存在一种或多种特定关系的数据元素的集合.通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率.数据结构往往同高效的检索算法和索引技术有关. 逻辑结构包括:1.集合数据结构中的元素之间除了“同属一个集合” 的相互关系外,别无其他关系: 2.线性结构数据结构中的元素存在一对一的相互关系: 3.树形结构数据结构中的元素存在一对多的相互关系: 4.图形结构数据结构中的元素存在多对多的相互关系. ================ 效果:1.

数据结构_二叉树后序遍历

/* 后序遍历二叉树 思路: 1,若当前结点没有左右孩子,则访问并出栈 2,若当前结点有左孩子或右孩子,并且孩子被访问过,则访问并出栈(若当前结点有左右孩子,只要有一个孩子已被访问,那么它的两个孩子都已被访问,这与入栈顺序有关,它的孩子在栈中一定在它的上方) 3,若当前结点有左孩子或右孩子,并且都没有被访问,那么先将右孩子入栈,再将左孩子入栈 */ void beh_Order(BiTree T) { InitStack(S); BiTree pCur,pPre=NULL,p; Push(s,T

数据结构_二叉树先序遍历

/* 二叉树先序遍历 思路: 1,先访问当前结点,将其入栈(其可能有右孩子) 2,若其存在左结点,执行1 3,若不存在左结点,则将栈顶元素出栈,若其不存在右孩子,继续出栈,若有右孩子,执行1 */ void pre_Order(BTree T) { InitStack(S); BiTree pCur=T; while(pCur || !IsEmpty(S)) //这里的IsEmpty好像不需要 { visit(pCur); Push(S,pCur); pCur = pCur->lchild; w

数据结构_二叉树

//二叉树BST class Node { constructor (data) { this.data = data this.left = null this.right = null } } class BST { constructor () { this.root = null } insert (data) { let newNode = new Node(data) if (!this.root) this.root = newNode else { this.insertNode

数据结构课程设计题目四_二叉树

本文出自:http://blog.csdn.net/svitter 题目4:二叉树 给出一颗无线的二叉树.树的每一个结点用一整数对标识.二叉树构造如下 树根被标识为(1, 1): 如果一个结点被标识为(a, b), 则其左孩子被标识为(a+b,b),右孩子被标识为(a, a+b).现在给出某一结点(a, b),求树根到该结点的最短路径,并且同时求出从树根出发向左走和向右走的次数.建议完成人数1人. 注:此处使用了STL_stack库函数,是不允许的,我图方便. //===============

0038数据结构之堆和优先队列

优先队列:出队顺序和入队顺序无关,而是和优先级有关(优先级高的先出队) 如果使用普通线性结构或者顺序线性结构实现优先队列,出队或者入队总有一方是O(n)级别的:如果使用堆实现优先队列,能使入队和出队的时间复杂度都是O(logn),效率是极高的. 二叉堆是一颗完全二叉树,不一定是满二叉树,但是确实节点的那部分一定是在整棵树的右下侧.满足的规律:1)根节点最大, 2)确实节点的那部分在整棵树的右下侧.(低层次的节点不一定大于高层次的节点) 下图是一颗最大堆: 可以用数组存储: 从数组1位置开始存储:

数据结构-堆实现优先队列(java)

队列的特点是先进先出.通常都把队列比喻成排队买东西,大家都很守秩序,先排队的人就先买东西.但是优先队列有所不同,它不遵循先进先出的规则,而是根据队列中元素的优先权,优先权最大的先被取出.这就很像堆的特征:总是移除优先级最高的根节点. 重点:优先级队列,是要看优先级的,谁的优先级更高,谁就先得到权限.不分排队的顺序! 上篇文章解释了堆的概念实现,现在用堆实现优先队列: //最大堆 import java.util.ArrayList; public class Heap<E extends Com

堆与优先队列

当我们需要高效的完成以下操作时: 1.插入一个元素 2.取得最小(最大)的数值,并且删除 能够完成这种操作的数据结构叫做优先队列 而能够使用二叉树,完成这种操作的数据结构叫做堆(二叉堆) 堆与优先队列的时间复杂度: 若共有n个元素,则可在O(logn)的时间内完成上述两种操作 堆的结构如下图: 堆最重要的性质就是儿子的值一定不小于父亲的值,且堆从上到下,从左到右紧密排列. 堆的操作: 当我们希望向堆中插入元素时,堆的内部会进行如下操作(以插入元素3为例): (1.在堆的末尾插入该值) (2.不断