Typescript 版算法实现
1 )方案一:参考最小堆类实现最大堆类及实现排序
class MaxHeap {
heap: number[] = [];
// 交换节点位置
swap(i, j) {
[this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
}
// 获得父节点
getParentIndex(i) {
return (i - 1) >> 1;
}
// 获取左子节点
getLeftIndex(i) {
return (i << 1) + 1; // 极客写法
}
// 获取右子节点
getRightIndex(i) {
return (i << 1) + 2;
}
// 向上移动
shiftUp(index) {
// 如果到了堆顶元素,index是0,则不要再上移了
if(!index) return;
const parentIndex = this.getParentIndex(index)
if(this.heap[parentIndex] < this.heap[index]) {
this.swap(parentIndex, index)
this.shiftUp(parentIndex)
}
}
// 下移
shiftDown(index) {
// 边界1:如果到了堆尾元素,则不要再下移了
if(index >= this.heap.length - 1) return;
const size = this.size();
const leftIndex = this.getLeftIndex(index);
const rightIndex = this.getRightIndex(index);
if (leftIndex < size && this.heap[leftIndex] > this.heap[index]) {
this.swap(leftIndex, index);
this.shiftDown(leftIndex);
}
if (rightIndex < size && this.heap[rightIndex] > this.heap[index]) {
this.swap(rightIndex, index);
this.shiftDown(rightIndex);
}
}
// 插入
insert(value) {
this.heap.push(value);
this.shiftUp(this.heap.length - 1);
}
// 删除堆顶
pop() {
// pop()方法删除数组最后一个元素并返回,赋值给堆顶
if (this.heap.length <= 1) return;
this.heap[0] = this.heap.pop();
// 对堆顶重新排序
this.shiftDown(0);
}
// 获取堆顶
peak() {
return this.heap[0];
}
// 获取堆的大小
size() {
return this.heap.length;
}
sort(arr) {
// 1. 先构建一个最小堆
arr.forEach((n) => {
this.insert(n);
});
// 2. 开始依次排序,注意这个边界, pop不能是1,否则会造成死循环
const result = [];
while(this.heap.length > 1) {
result.push(this.peak());
this.pop();
}
// 3. 处理最后一个
result.push(this.peak());
this.heap = result;
return result;
}
}
const mh = new MaxHeap();
mh.sort([1, 10, 9, 5, 3, 11, 3, 9, 11, 13, 1, -1, 98]);
console.log(mh.heap); // [98, 13, 11, 11, 10, 9, 9, 5, 3, 3, 1, 1, -1]
- 实现最小堆类参考:https://blog.csdn.net/Tyro_java/article/details/133468244
- 这里排序需要注意的是:先构建的最小堆,并不是排好序的,只是最小值在堆顶,O(logn)
- 循环中每次把最小值取出来, 注意pop下移操作时的边界问题,O(nlogn)
2 )方案二:另一种方式实现最大堆类及实现排序
class MaxHeap {
heap: number[] = []
// 交换两个元素
static swap (arr, i, j) {
if (i === j) return;
[arr[i], arr[j]] = [arr[j], arr[i]];
}
// 构建最大堆的过程,递归
static maxHeapify (Arr, i, size) {
// 左节点(索引)
const l = (i << 1) + 1
// 右节点
const r = (i << 1) + 2
let largest = i;
// 父节点i和左节点l做比较取最大
if (l <= size && Arr[l] < Arr[largest]) largest = l;
// 右节点和最大值比较
if (r <= size && Arr[r] < Arr[largest]) largest = r;
if (largest !== i) {
MaxHeap.swap(Arr, i, largest);
MaxHeap.maxHeapify(Arr, largest, size);
}
}
sort () {
const iArr = this.heap;
const n = iArr.length;
if (n <= 1) return iArr;
// 这里,从最后一个父节点开始构建最大堆, 因为最后一个父节点到第一个父节点就是一次完整的构建最大堆的过程,完成后堆顶就是最大值
for (let i = Math.floor(n / 2); i >= 0; i--) {
MaxHeap.maxHeapify(iArr, i, n); // 这里最后一个参数 n 是完整的堆
}
// 减而治之
for (let j = 0; j < n; j++) {
MaxHeap.swap(iArr, 0, n - 1 - j); // 堆顶与最后一项互换, 堆顶被破坏, 堆顶变成最后一项
MaxHeap.maxHeapify(iArr, 0, n - 1 - j - 1); // 这里逐渐缩小堆的规模,注意后面的减1,因为最后一个元素是排好序的最大值
}
return iArr
}
}
const mh = new MaxHeap();
mh.heap = [1, 10, 9, 5, 3, 11, 3, 9, 11, 13, 1, -1, 98]
mh.sort();
console.log(mh.heap); // [98, 13, 11, 11, 10, 9, 9, 5, 3, 3, 1, 1, -1]
- 这个排序的精髓是:在这个排序里先构建一次最大堆,获取排好序的最大值后,逐渐减而治之
Python3 版算法实现
1 ) 方案1
class MaxHeap:
def __init__(self):
self.heap = []
# 交换节点位置
def swap(self, i, j):
self.heap[i], self.heap[j] = self.heap[j], self.heap[i]
# 获得父节点
def get_parent_index(self, i):
return (i - 1) >> 1
# 获取左子节点
def get_left_index(self, i):
return (i << 1) + 1
# 获取右子节点
def get_right_index(self, i):
return (i << 1) + 2
# 向上移动
def shift_up(self, index):
if index == 0:
return
parent_index = self.get_parent_index(index)
if self.heap[parent_index] < self.heap[index]:
self.swap(parent_index, index)
self.shift_up(parent_index)
# 下移
def shift_down(self, index):
if index >= len(self.heap) - 1:
return
size = self.size()
left_index = self.get_left_index(index)
right_index = self.get_right_index(index)
if left_index < size and self.heap[left_index] > self.heap[index]:
self.swap(left_index, index)
self.shift_down(left_index)
if right_index < size and self.heap[right_index] > self.heap[index]:
self.swap(right_index, index)
self.shift_down(right_index)
# 插入
def insert(self, value):
self.heap.append(value)
self.shift_up(len(self.heap) - 1)
# 删除堆顶
def pop(self):
if len(self.heap) <= 1:
return
self.heap[0] = self.heap.pop()
self.shift_down(0)
# 获取堆顶
def peak(self):
return self.heap[0] if self.heap else None
# 获取堆的大小
def size(self):
return len(self.heap)
# 排序
def sort(self, arr):
for n in arr:
self.insert(n)
result = []
while self.size() > 1:
result.append(self.peak())
self.pop()
result.append(self.peak())
self.heap = result
return result
def main():
mh = MaxHeap()
sorted_array = mh.sort([1, 10, 9, 5, 3, 11, 3, 9, 11, 13, 1, -1, 98])
print(sorted_array) # 应该输出 [98, 13, 11, 11, 10, 9, 9, 5, 3, 3, 1, 1, -1]
if __name__ == "__main__":
main()
2 )方案2
class MaxHeap:
def __init__(self):
self.heap = []
# 交换两个元素
@staticmethod
def swap(arr, i, j):
if i == j:
return
arr[i], arr[j] = arr[j], arr[i]
# 构建最大堆的过程,递归
@staticmethod
def max_heapify(arr, i, size):
l = (i << 1) + 1
r = (i << 1) + 2
largest = i
if l <= size and arr[l] > arr[largest]:
largest = l
if r <= size and arr[r] > arr[largest]:
largest = r
if largest != i:
MaxHeap.swap(arr, i, largest)
MaxHeap.max_heapify(arr, largest, size)
# 排序
def sort(self):
i_arr = self.heap
n = len(i_arr)
if n <= 1:
return i_arr
for i in range(n // 2, -1, -1):
MaxHeap.max_heapify(i_arr, i, n - 1)
for j in range(n):
MaxHeap.swap(i_arr, 0, n - 1 - j)
MaxHeap.max_heapify(i_arr, 0, n - 2 - j)
return i_arr
def main():
mh = MaxHeap()
mh.heap = [1, 10, 9, 5, 3, 11, 3, 9, 11, 13, 1, -1, 98]
sorted_array = mh.sort()
print(sorted_array) # 应该输出 [98, 13, 11, 11, 10, 9, 9, 5, 3, 3, 1, 1, -1]
if __name__ == "__main__":
main()
Golang 版算法实现
1 ) 实现1
package main
import (
"fmt"
)
type MaxHeap struct {
heap []int
}
// 交换节点位置
func (h *MaxHeap) swap(i, j int) {
h.heap[i], h.heap[j] = h.heap[j], h.heap[i]
}
// 获得父节点
func (h *MaxHeap) getParentIndex(i int) int {
return (i - 1) >> 1
}
// 获取左子节点
func (h *MaxHeap) getLeftIndex(i int) int {
return (i << 1) + 1
}
// 获取右子节点
func (h *MaxHeap) getRightIndex(i int) int {
return (i << 1) + 2
}
// 向上移动
func (h *MaxHeap) shiftUp(index int) {
if index == 0 {
return
}
parentIndex := h.getParentIndex(index)
if h.heap[parentIndex] < h.heap[index] {
h.swap(parentIndex, index)
h.shiftUp(parentIndex)
}
}
// 下移
func (h *MaxHeap) shiftDown(index int) {
if index >= len(h.heap)-1 {
return
}
size := h.size()
leftIndex := h.getLeftIndex(index)
rightIndex := h.getRightIndex(index)
if leftIndex < size && h.heap[leftIndex] > h.heap[index] {
h.swap(leftIndex, index)
h.shiftDown(leftIndex)
}
if rightIndex < size && h.heap[rightIndex] > h.heap[index] {
h.swap(rightIndex, index)
h.shiftDown(rightIndex)
}
}
// 插入
func (h *MaxHeap) insert(value int) {
h.heap = append(h.heap, value)
h.shiftUp(len(h.heap) - 1)
}
// 删除堆顶
func (h *MaxHeap) pop() {
if len(h.heap) <= 1 {
return
}
h.heap[0] = h.heap[len(h.heap)-1]
h.heap = h.heap[:len(h.heap)-1]
h.shiftDown(0)
}
// 获取堆顶
func (h *MaxHeap) peak() *int {
if len(h.heap) == 0 {
return nil
}
return &h.heap[0]
}
// 获取堆的大小
func (h *MaxHeap) size() int {
return len(h.heap)
}
// 排序
func (h *MaxHeap) sort(arr []int) []int {
for _, n := range arr {
h.insert(n)
}
result := make([]int, 0, len(arr))
for h.size() > 1 {
result = append(result, *h.peak())
h.pop()
}
result = append(result, *h.peak())
h.heap = result
return result
}
func main() {
mh := &MaxHeap{}
sortedArray := mh.sort([]int{1, 10, 9, 5, 3, 11, 3, 9, 11, 13, 1, -1, 98})
fmt.Println(sortedArray) // 应该输出 [98, 13, 11, 11, 10, 9, 9, 5, 3, 3, 1, 1, -1]
}
2 )实现2
package main
import (
"fmt"
)
type MaxHeap struct {
heap []int
}
// 交换两个元素
func (h *MaxHeap) swap(arr []int, i, j int) {
if i == j {
return
}
arr[i], arr[j] = arr[j], arr[i]
}
// 构建最大堆的过程,递归
func (h *MaxHeap) maxHeapify(arr []int, i, size int) {
l := (i << 1) + 1
r := (i << 1) + 2
largest := i
if l <= size && arr[l] > arr[largest] {
largest = l
}
if r <= size && arr[r] > arr[largest] {
largest = r
}
if largest != i {
h.swap(arr, i, largest)
h.maxHeapify(arr, largest, size)
}
}
// 排序
func (h *MaxHeap) sort() []int {
iArr := h.heap
n := len(iArr)
if n <= 1 {
return iArr
}
for i := n / 2; i >= 0; i-- {
h.maxHeapify(iArr, i, n-1)
}
for j := 0; j < n; j++ {
h.swap(iArr, 0, n-1-j)
h.maxHeapify(iArr, 0, n-2-j)
}
return iArr
}
func main() {
mh := &MaxHeap{
heap: []int{1, 10, 9, 5, 3, 11, 3, 9, 11, 13, 1, -1, 98},
}
sortedArray := mh.sort()
fmt.Println(sortedArray) // 应该输出 [98, 13, 11, 11, 10, 9, 9, 5, 3, 3, 1, 1, -1]
}