漫画算法-学习笔记(12)

漫画算法-小灰的算法之旅(12)

1. 什么是优先队列

队列的特点是什么?

队列的特点: 先进先出(FIFO),入队列,将新元素置于队尾;出队列,队头元素最先被移出。

什么是优先队列?

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

  • 最大优先队列:无论入队顺序如何,都是当前最大的元素优先出队。
  • 最小优先队列:无论入队顺序如何,都是当前最小的元素优先出队。

要实现优先队列,利用线性数据结构并非不能实现,但时间复杂度较高。可以采用二叉堆实现

2. 优先队列的实现

我们知道二叉堆的特性:

  • 最大堆的堆顶是整个堆中的最大元素
  • 最小堆的堆顶是整个堆中的最小元素

因此可以采用,最大堆来实现最大优先队列,这样的话,每次入队操作就是堆的插入操作,每次出队操作就是删除堆顶节点

入队操作

具体步骤如下:

插入新节点5

新节点5**"上浮"操作**到合适位置。

出队操作

具体步骤如下:

让原堆顶节点10出队

把最后一个节点1替换到堆顶位置

节点1**"下沉"操作**,节点9成为新堆顶。

时间复杂度

优先队列的入队和出队操作,时间复杂度是多少?

因为二叉堆节点“上浮”和“下沉”的时间复杂度都是O(logn);所以优先队列入队和出队的时间复杂度都是O(logn).

3. 代码实现


private int[] array;
private int size;
public PriorityQueue(){
  //队列初始长度为32
  array=new int[32];
}

/**
* 入队
* param key 入队元素
*/

public void enQueue(int key){
  //队列长度超出范围,扩容
  if(size>=array.length){
    resize();
  }
  array[size++]=key;
  upAdjust();
}

/**
* 出队
*/
public int deQueue()throws Exception{
  if(size<=0){
    throw new Exception("the Queue is empty");
  }
  // 获取堆顶元素
  int head=array[0];
  //让最后一个元素移动到堆顶
  array[0]=array[--size];
  downAdjust();
  return head;
}

/**
* "上浮"调整
*/
public void upAdjust(){
  int childIndex =size-1;
  int parentIndex=(childIndex-1)/2;
  //temp保存插入的叶子节点值,用于最后的赋值
  int temp=array[childIndex];
  while(childIndex>0 && temp>array[parentIndex]){
    //无须真正交换,单向赋值即可
    array[childIndex]=array[parentIndex];
    childIndex=parentIndex;
    parentIndex=parentIndex/2;
  }
  array[childIndex]=temp;
}

/**
* “下沉”操作
*/
private void downAdjust(){
  //temp保存父节点的值,用于最后的赋值
  int parentIndex=0;
  int temp=array[parentIndex];
  int childIndex=1;
  while(childIndex<size){
    //如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子,
    if(childIndex+1 <size && array[childIndex+1] >array[childIndex]){
      childIndex++;
    }
    // 如果父节点大于任何一个孩子的值,直接跳出
    if(temp>=array[childIndex]){
      break;
    }
    // 无须真正交互,单向赋值即可
    array[parentIndex]=array[childIndex];
    parentIndex=childIndex;
    childIndex=2*childIndex+1;
  }
  array[parentIndex]=temp;
}

/** 
* 队列扩容
*/
private void resize(){
  //队列容量翻倍
  int newSize=this.size*2;
  this.array=Array.copyOf(this.array,newSize);
}

publice static void main(String[] args) throws Exception{
  priorityQueue priorityQueue =new PriorityQueue();
  priorityQueue.enQueue(3);
  priorityQueue.enQueue(5);
  priorityQueue.enQueue(10);
  priorityQueue.enQueue(2);
  priorityQueue.enQueue(7);
  System.out.println("出队元素"+priorityQueue.deQueue());
  System.out.println("出队元素"+priorityQueue.deQueue());
}

4. 总结

什么是树?

是n个节点的有限集合,有且仅有一个特定的称为根的节点,当n>1时,其余节点可以分为m个互不相交的有限集合,每一个集合本身右是一个树,并称为根的子树。

什么是二叉树?

二叉树是树的一种特殊形式,每一个节点最多有两个孩子节点。二叉树包含完全二叉树、满二叉树两种特殊形式。

二叉树的遍历方式有几种

根据遍历节点之间的关系,可以分为前序遍历、中序遍历、后序遍历、层序遍历几种方式;从更宏观的角度划分,可以划分为深度优先遍历广度优先遍历

什么是二叉堆

二叉堆是一种特殊的完全二叉树,分为最大堆最小堆

最大堆中,任何一个父节点的值,都大于或等于它左、右孩子节点的值。

最小堆中,任何一个父节点的值,都小于或等于他左、右孩子节点的值。

什么是优先队列

优先队列分为最大优先队列最小优先队列

最大优先队列: 无论入队顺序如何,当前最大的元素都会优先出队列,基于最大堆实现。

最小优先队列:无论入队顺序如何,当前最小的元素都会优先出队,基于最小堆实现。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值