第十节:高阶队列详解(双端队列、优先级队列)

一.  双端队列

1. 回顾

    默认的队列是先进先出的, 即只允许在front前端出队,在near后端入队

2. 什么是双端队列?

   允许在队列的两端进行出队 和 入队

3. 实操

  继承之前的队列MyQueue,然后新增addFront、removeBack两个方法即可

  PS: 双端队列了解即可,实用性不是很大,违背了队列的特性,这里不做详细测试了

import MyQueue from '../02-队列结构/01-实现队列结构';

/**
 * 双端队列
 */
class MyDeque<T> extends MyQueue<T> {
	/**
	 * 01-在队首入队
	 * @param value 添加的元素
	 */
	addFront(value: T) {
		this.array.unshift(value);
	}
	/**
	 * 02-在队尾出队
	 * @returns 返回删除的元素
	 */
	removeBack(): T | undefined {
		return this.array.pop();
	}
}

 

二.  优先级队列

1. 什么是优先级队列?

   优先级队列(Priority Queue)是一种比普通队列更加高效的数据结构。它每次出队的元素都是具有最高优先级的,可以理解为元素按照关键字进行排序。

   优先级队列可以用数组、链表等数据结构来实现,但是堆是最常用的实现方式

2. 一些生活场景?

   登机顺序,头等舱有限;医院急诊

3. 补充对象大小的比较方式

 默认两个对象实例之间是没法比较的,无论怎么比较都是false

 解决方案:声明一个valueof方法,里面return返回需要根据比较的属性,如下Person2的两个实例,就可以根据age属性比较大小了 


//对象1
class Person1 {
	name: string;
	age: number;
	constructor(name: string, age: number) {
		this.name = name;
		this.age = age;
	}
}
{
	console.log('---------------Person1对象比较---------------------');
	let p1 = new Person1('ypf1', 18);
	let p2 = new Person1('ypf2', 19);
	console.log(`p1<p2的结果:${p1 < p2}`); //false
	console.log(`p1>p2的结果:${p1 > p2}`); //false
}

//对象2
class Person2 {
	name: string;
	age: number;
	constructor(name: string, age: number) {
		this.name = name;
		this.age = age;
	}
	/**
	 * 对象比较
	 * @returns 根据返回的属性进行对象比较
	 */
	valueOf() {
		return this.age;
	}
}
{
	console.log('---------------Person2对象比较---------------------');
	let p1 = new Person2('ypf1', 18);
	let p2 = new Person2('ypf2', 19);
	console.log(`p1<p2的结果:${p1 < p2}`); //true
	console.log(`p1>p2的结果:${p1 > p2}`); //false
}

4. 实现方式1

(1) 思路:

  创建优先级节点类,保存在堆中,此时堆中存放的就是这个优先级节点的实例对象。

  这个优先级节点类需要实现valueof方法,用于对象之间大小的比较, 否则存入堆的对象无法比较大小  

(2).实现的方法

  enqueue、dequeue、peek、peek、size 


/**
 * 优先级节点类
 */
class PriorityNode<T> {
	priority: number;
	value: T;
	constructor(value: T, priority: number) {
		this.priority = priority;
		this.value = value;
	}
	// 表示该类根据priority属性进行大小比较
	valueOf() {
		return this.priority;
	}
}

/**
 * 优先级队列
 */
class PriorityQueue1<T> {
	//底层用堆存储(默认为最大堆)
	private heap: Heap<PriorityNode<T>> = new Heap();

	/**
	 * 01-入队
	 * @param val 内容
	 * @param priority 优先级
	 */
	enqueue(val: T, priority: number) {
		let pNode = new PriorityNode(val, priority);
		this.heap.insert(pNode);
	}
	/**
	 * 02-出队
	 * @returns 返回出队的元素 或 不存在为undefined
	 */
	dequeue(): T | undefined {
		return this.heap.delete()?.value;
	}
	/**
	 * 03-返回队首元素,不进行任何操作
	 * @returns 返回队首元素 或 不存在为undefined
	 */
	peek(): T | undefined {
		return this.heap.peek()?.value;
	}
	/**
	 * 04-队列是否为空
	 * @returns
	 */
	isEmpty() {
		return this.heap.isEmpty();
	}
	/**
	 * 05-返回队列元素个数
	 * @returns
	 */
	size() {
		return this.heap.size();
	}
}

测试:

{
	console.log('-------------------实现方式1测试--------------------------');
	let pQueue1 = new PriorityQueue1<string>();
	pQueue1.enqueue('ypf1', 18);
	pQueue1.enqueue('ypf2', 66);
	pQueue1.enqueue('ypf3', 20);
	pQueue1.enqueue('ypf4', 30);

	//输出:ypf2 ypf4 ypf3 ypf1
	while (!pQueue1.isEmpty()) {
		console.log(pQueue1.dequeue());
	}
}

5. 实现方式2

  数据自身返回优先级的比较值, 即插入的数据Student类,在类内部实现valueof


/**
 * 优先级队列
 */
class PriorityQueue2<T> {
	//底层用堆存储(默认为最大堆)
	private heap: Heap<T> = new Heap();

	/**
	 * 01-入队
	 * @param val 内容
	 */
	enqueue(val: T) {
		this.heap.insert(val);
	}
	/**
	 * 02-出队
	 * @returns 返回出队的元素 或 不存在为undefined
	 */
	dequeue(): T | undefined {
		return this.heap.delete() ?? undefined;
	}
	/**
	 * 03-返回队首元素,不进行任何操作
	 * @returns 返回队首元素 或 不存在为undefined
	 */
	peek(): T | undefined {
		return this.heap.peek();
	}
	/**
	 * 04-队列是否为空
	 * @returns
	 */
	isEmpty() {
		return this.heap.isEmpty();
	}
	/**
	 * 05-返回队列元素个数
	 * @returns
	 */
	size() {
		return this.heap.size();
	}
}

测试:


{
	console.log('-------------------实现方式2测试--------------------------');
	class Student {
		name: string;
		score: number;
		constructor(name: string, score: number) {
			this.name = name;
			this.score = score;
		}
		valueOf() {
			return this.score;
		}
	}

	let pQueue2 = new PriorityQueue2<Student>();

	pQueue2.enqueue(new Student('ypf1', 18));
	pQueue2.enqueue(new Student('ypf2', 66));
	pQueue2.enqueue(new Student('ypf3', 20));
	pQueue2.enqueue(new Student('ypf4', 30));

	//输出:ypf2 ypf4 ypf3 ypf1  [实际格式:Student { name: 'ypf2', score: 66 }]
	while (!pQueue2.isEmpty()) {
		console.log(pQueue2.dequeue());
	}
}

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2024-01-08 10:34  Yaopengfei  阅读(17)  评论(1编辑  收藏  举报