源码如下:
import { DataStruct_Array } from "../02-Arrays/DataStruct_Array"; //最大二叉堆也需要具有可比较性 type Comparable = { compareto(that: Comparable): number; equals(that: Comparable): boolean; } //最大二叉堆可比较性的数据类型 export class MaxBH_Data implements Comparable { constructor(private e: any) { } compareto(that: MaxBH_Data): number { return this.e - that.e; } equals(that: MaxBH_Data): boolean { return this.e === that.e; } } /** * Autor: Created by 李清风 on 2021-01-03. * Desc: 二叉堆(是一颗完全二叉树) * 满二叉树:除了叶子节点,所有的节点都有左右节点 * 完全二叉树:她不一定是一个满二叉树,但是它缺失部分,一定是在右下侧 */ export class DataStruct_BinaryMaxHeap<T>{ //从底层实现一个最大堆 //我使用数组来存储二叉堆 //公式:(0号设置为空的情况) //parent(i) = i/2; //left child (i) = 2*i; //right child (i) = 2*i + 1; //(0号不设置为空的情况) //parent(i) = (i-1)/2; //left child (i) = 2*i+1; //right child (i) = 2*i + 2; private array: DataStruct_Array<T>; //private size:number; //当然你也可以初始化一个不知道多少个元素的二叉堆,扩容我帮你处理 public constructor(capacity: number) { this.array = new DataStruct_Array<T>(capacity) } public size(): number { return this.array.getSize(); } public isEmpty(): boolean { return this.array.isEmpty(); } //返回完全二叉树中,index索引对应的父亲节点索引 private parent(index: number) { if (index == 0) { throw new Error("index-0 doesn't hava parent."); } return (index - 1) / 2; } //返回完全二叉堆中,index索引对应的左孩子的节点索引 private leftChild(index: number): number { return index * 2 + 1; } //返回完全二叉堆中,index索引对应的右孩子的i节点索引 private rightChild(index: number): number { return index * 2 + 2; } //往堆中添加元素 public add(e: T) { this.array.addLast(e); //上浮指定的元素 this.siftUp(this.array.getSize() - 1); } private siftUp(k: number) { //上浮限定:不能是根节点&&如果小于其父亲节点 //this.array.get(this.parent(k)) 当前k节点的父亲节点元素 //this.array.get(k) 当前k节点的元素 while (k > 0 && this.array.get(this.parent(k)).compareto(this.array.get(k)) < 0) { this.array.swap(k, this.parent(k)); k = this.parent(k); } } //从堆中取出元素,下沉操作 public extractMax() { let ret = this.findMax(); //将0索引和堆中最后一个元素交换位置,也就是将堆中最大元素放到末尾 this.array.swap(0, this.array.getSize() - 1); this.array.removeLast();//删除末尾 this.siftDown(0);//数据开始下沉操作 return ret; } //找出堆中最大元素 public findMax(): T { if (this.array.getSize() == 0) { //为空 throw new Error("Can not findMax when heap is empty!"); } return this.array.get(0); } siftDown(k: number) { while (this.leftChild(k) < this.array.getSize()) { let j = this.leftChild(k); if (j + 1 < this.array.getSize() && this.array.get(j + 1).compareto(this.array.get(j)) > 0) { j = this.rightChild(k); } //array[j]是leftChild和rightChild中的最大值 if (this.array.get(k).compareto(this.array.get(j)) >= 0) { break; } this.array.swap(k, j); k = j; //准备下一次循环 } } //取出最大元素后,替换成新元素e public replace(e) { let ret = this.findMax(); this.array.set(0, e); this.siftDown(0); return ret; } }
二叉堆HeapHeapify操作的单独拿出来实现
/** * Autor: Created by 李清风 on 2020-12-17. * Desc: 二叉堆heapify操作的实现 */ export class DataStruct_HeapHeapify<T>{ private array: DataStruct_HeapifyArray<T>; //用户传递进来一个数组,我们将数组转换成堆的形状 public constructor(arr: T[]) { this.array = new DataStruct_HeapifyArray<T>(arr); for (let i = this.parent(arr.length - 1); i >= 0; i--) { this.siftDown(i); //实现heapify过程 } } public size(): number { return this.array.getSize(); } public isEmpty(): boolean { return this.array.isEmpty(); } //返回完全二叉树中,index索引对应的父亲节点索引 private parent(index: number) { if (index == 0) { throw new Error("index-0 doesn't hava parent."); } return (index - 1) / 2; } //返回完全二叉堆中,index索引对应的左孩子的节点索引 private leftChild(index: number): number { return index * 2 + 1; } //返回完全二叉堆中,index索引对应的右孩子的i节点索引 private rightChild(index: number): number { return index * 2 + 2; } //往堆中添加元素 public add(e: T) { this.array.addLast(e); //上浮指定的元素 this.siftUp(this.array.getSize() - 1); } private siftUp(k: number) { while (k > 0 && this.array.get(this.parent(k)).compareto(this.array.get(k)) < 0) { this.array.swap(k, this.parent(k)); k = this.parent(k); } } //从堆中取出元素,下沉操作 public extractMax() { let ret = this.findMax(); //将0索引和堆中最后一个元素交换位置,也就是将堆中最大元素放到末尾 this.array.swap(0, this.array.getSize() - 1); this.array.removeLast();//删除末尾 this.siftDown(0);//数据开始下沉操作 return ret; } //找出堆中最大元素 public findMax() { if (this.array.getSize() == 0) { //为空 throw new Error("Can not findMax when heap is empty!"); } return this.array.get(0); } siftDown(k: number) { while (this.leftChild(k) < this.array.getSize()) { let j = this.leftChild(k); if (j + 1 < this.array.getSize() && this.array.get(j + 1).compareto(this.array.get(j)) > 0) { j = this.rightChild(k); } //array[j]是leftChild和rightChild中的最大值 if (this.array.get(k).compareto(this.array.get(j)) >= 0) { break; } this.array.swap(k, j); k = j; //准备下一次循环 } } } /** * Autor: Created by 李清风 on 2020-12-17. * Desc: 针对二叉堆heapify操作的实现,而创建的数组 */ class DataStruct_HeapifyArray<T> { private data: T[]; private size: number; //用来实现,用户将数组转换成二叉堆 public constructor(arr: T[]) { this.data = new Array<T>(arr.length); for (let i = 0; i < arr.length; i++) { this.data[i] = arr[i]; } this.size = arr.length; } public getSize(): number { return this.size; } public getCapacity(): number { return this.data.length } public isFull(): boolean { return this.size == this.data.length; } public isEmpty(): boolean { return this.size == 0; } //在数组尾添加元素 public addLast(e: T) { this.add(this.size, e); } //添加元素到首 public addFirst(e: T) { this.add(0, e); } public add(index: number, e: T) { if (index < 0 || index > this.size) { throw new Error("LogError:Add Failed.Require index >=0 and index<size."); } if (this.size == this.data.length) { this.resize(this.data.length * 2);//对数组进行扩容 } for (let i: number = this.size - 1; i >= index; i--) { this.data[i + 1] = this.data[i]; } this.data[index] = e; this.size++; } //因为使用了array来构造,这里只提供扩容的思路 private resize(expandCount: number) { let newData: T[] = new Array<T>(expandCount); for (let i = 0; i < this.size; i++) { newData[i] = this.data[i]; } this.data = newData; //内存引用地址转,等待GC回收 } //移除指定index的元素 public remove(index: number): T { if (index < 0 || index > this.size) { throw new Error("LogError:Add Failed.Require index >=0 and index<size."); } let ret: T = this.data[index]; for (let i = index + 1; i < this.size; i++) { this.data[i - 1] = this.data[i]; //移位 } this.size--;//更新size this.data[this.size] = null; //引用类型要注意释放loitering objects if (this.size == this.data.length / 2) { this.resize(this.data.length); } return ret; } public removeFirst() { return this.remove(0); } public removeLast() { return this.remove(this.size - 1); } public removeElement(e: T) { let index = this.find(e); if (index > 0) { this.remove(index); } } public get(index: number): T { if (index < 0 || index > this.size) { throw new Error("LogError:Add Failed.Require index >=0 and index<size."); } return this.data[index]; } public getFirst(): T { return this.get(0); } public getLast(): T { return this.get(this.size - 1); } public set(index: number, e: T) { if (index < 0 || index > this.size) { throw new Error("LogError:Add Failed.Require index >=0 and index<size."); } this.data[index] = e; } public contains(e: T): boolean { for (let i = 0; i < this.size; i++) { if (this.data[i] == e) { return true; } } return false; } //寻找符合的元素,可以使用二分查找实现,但是需要对数组指定sort函数 public find(e: T): number { for (let i = 0; i < this.size; i++) { if (this.data[i] == e) { return i; } } return -1; } //针对二叉堆扩展的交换函数 public swap(i: number, j: number) { if (i < 0 || i >= this.size || j < 0 || j >= this.size) { throw new Error("Index is illegal"); } let temp: T = this.data[i]; this.data[i] = this.data[j]; this.data[j] = temp; } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。