用数组实现队列
enqueue:元素入队
dequeue:元素出队
size:返回队列长度
showHead: 查看队头元素
class Queue {constructor() {this.dataStore = [];}enqueue(element) {this.dataStore.push(element);}dequeue() {return this.dataStore.shift();}size() {return this.dataStore.length();}showHead() {return this.dataStore[0];}}
用数组和两个指针实现队列
class Queue {constructor() {this.dataStore = [];this.rear = -1; //指向最后一个元素this.front = -1; // 指向第一个元素的下标-1}enqueue(element) {// 入队队尾下标+1this.dataStore[++this.rear] = element;}dequeue() {// 出队队首下标+1if (this.isEmpty()) return;return this.dataStore[++this.front];}size() {return this.rear - this.front;}showHead() {// front+1才是队首元素if (!this.isEmpty()) return this.dataStore[this.front+1];}isEmpty() {return this.rear === this.front;}}
使用数组实现环形队列
class CircularQueue {constructor(maxSize) {this.maxSize = maxSize;this.dataStore = [];this.rear = 0; //只要rear与front相等就是空队列,初始值无要求this.front = 0;}enqueue(element) {// 入队队尾下标+1,取模达到环形队列效果if (this.isFull()) {return console.log("full");}this.rear = (this.rear + 1) % this.maxSize;this.dataStore[this.rear] = element;}dequeue() {// 出队队首下标+1,取模达到环形队列效果if (this.isEmpty()) {return console.log("empty");}this.front = (this.front + 1) % this.maxSize;return this.dataStore[this.front];}size() {// 加上maxSize以免出现负数的情况,再取模以免结果大于maxSizereturn (this.rear - this.front + this.maxSize) % this.maxSize;}showHead() {// front+1才是队首元素,同时取模以免溢出if (!this.isEmpty()) return this.dataStore[(this.front + 1) % this.maxSize];}isEmpty() {return this.rear === this.front;}isFull() {return (this.rear + 1) % this.maxSize === this.front;}}
把无序数组调整成大顶堆
// 调整位置方法function shiftDown(start, length, arr) {//从上而下调整堆的顺序let i = start;let j = 2 * i + 1;const temp = arr[i];while (j < length) {if (arr[j] < arr[j + 1] && j < length - 1) j++; //由于是大顶堆,取大的节点if (temp < arr[j]) {// 如果比开始节点大就往上浮,也可以理解成开始节点比叶子节点小就跟叶子节点换位,一直往下换到正确的位置arr[i] = arr[j];} else {//若左右两个叶子都比根节点小,由于这是个堆结构,它的叶子的叶子节点也会比根节点小,不需要继续调整break;}i = j;j = j * 2 + 1;}arr[i] = temp;}function makeHeap(arr) {// 把数组变成大顶堆for (let i = ~~(arr.length / 2) - 1; i > -1; i--) {//从下而上局部排序,直到把数组排成一个大顶堆shiftDown(i, arr.length, arr);}return arr;}
用大顶堆实现堆排序
function createArr(num) {const arr = new Array(num);for (let i = 0; i < num; i++) {arr[i] = ~~(Math.random() * 10000);}return arr;}// 调整位置方法function shiftDown(start, length, arr) {//从上而下调整堆的顺序let i = start;let j = 2 * i + 1;const temp = arr[i];while (j < length) {if (arr[j] < arr[j + 1] && j < length - 1) j++; //由于是大顶堆,取大的节点if (temp < arr[j]) {// 如果比开始节点大就往上浮,也可以理解成开始节点比叶子节点小就跟叶子节点换位,一直往下换到正确的位置arr[i] = arr[j];} else {//若左右两个叶子都比根节点小,由于这是个堆结构,它的叶子的叶子节点也会比根节点小,不需要继续调整break;}i = j;j = j * 2 + 1;}arr[i] = temp;}function makeHeap(arr) {// 把数组变成大顶堆for (let i = ~~(arr.length / 2) - 1; i > -1; i--) {//从下而上局部排序,直到把数组排成一个大顶堆shiftDown(i, arr.length, arr);}return arr;}function heapSort(arr) {arr = makeHeap(arr)// 依次把最大的元素剔除,然后调整剩余元素,这样可以按大小依次剔除元素,达到排序效果for (let j = arr.length - 1; j > 0; j--) {//把最大值与末尾调换,去除末尾元素,剩余再次调整成一个大顶堆,// 此时首位又是剩余元素的最大值,一直交换调整直到所有元素排序完毕const temp = arr[0];arr[0] = arr[j];arr[j] = temp;shiftDown(0, j, arr);}}// 测试堆排序的时间const arr = createArr(8000000);console.time();heapSort(arr);console.timeEnd();
用堆实现优先队列
class PriorityQueue {constructor(isMax) {this.isMax = isMax; // 是否优先最大值出列this.arr = [];}shiftMaxUp() { // 自底向上调整const { arr } = this;let i = arr.length - 1;let j = ~~((i + 1) / 2) - 1;let temp = arr[i];while (j >= 0) {if (temp > arr[j]) {arr[i] = arr[j];} else {break;}i = j;j = j = ~~((j + 1) / 2) - 1;}arr[i] = temp;}shiftMinUp() { // 自底向上调整const { arr } = this;let i = arr.length - 1;let j = ~~((i + 1) / 2) - 1;let temp = arr[i];while (j >= 0) {if (temp < arr[j]) {arr[i] = arr[j];} else {break;}i = j;j = j = ~~((j + 1) / 2) - 1;}arr[i] = temp;}shiftDownMax() { // 自顶向下调整const { arr } = this;if (!arr.length) {return arr;}let i = 0;let j = 2 * i + 1;let temp = arr[0];while (j < arr.length) {if (arr[j] < arr[j + 1] && j < arr.length - 1) {j++;}if (temp < arr[j]) {arr[i] = arr[j];} else {break;}i = j;j = j * 2 + 1;}arr[i] = temp;}shiftDownMin() { // 自顶向下调整const { arr } = this;if (!arr.length) {return arr;}let i = 0;let j = 2 * i + 1;let temp = arr[0];while (j < arr.length) {if (arr[j] > arr[j + 1] && j < arr.length - 1) {j++;}if (temp > arr[j]) {arr[i] = arr[j];} else {break;}i = j;j = j * 2 + 1;}arr[i] = temp;}add(num) { // 插入元素的时候在数组最后,也就是在叶子节点,需要往上调整位置const { arr, isMax } = this;arr.push(num);if (isMax) {this.shiftMaxUp();} else {this.shiftMinUp();}}delete() { // 删除时把队尾放到队首,此时可以从上到下调整位置const { arr, isMax } = this;arr[0] = arr[arr.length - 1];arr.pop();if (isMax) {this.shiftDownMax();} else {this.shiftDownMin();}}size() {return this.arr.length;}get() {return this.arr[0];}}
