堆排序
Dart实现堆排序
思想
利用堆(heap)这种数据结构来进行排序
堆
堆需要满足两个条件
- 完全二叉树
- 子节点的值总是小于或者大于它的父节点
规整某个节点 heapify
/**
* tree
* i 要规整的节点
* n 节点总数
*/
heapify(List tree, int i, int n) {
//保证节点i与他的子节点符合堆定义 即节点i的值在他和他的子节点中是最大的
int c1 = i * 2 + 1; //节点i的理论左子节点
int c2 = i * 2 + 2; //节点i的理论右子节点
int max = i;
if (c1 < n && tree[c1] > tree[max]) {
max = c1;
}
if (c2 < n && tree[c2] > tree[max]) {
max = c2;
}
//不满足堆定义,交换父节点和子节点中较大的那个,并对交换后的子节点进行规整
if (max != i) {
swap(tree, i, max);
heapify(tree, max, n);
}
}
swap(List tree, int i, int max) {
int temp = tree[i];
tree[i] = tree[max];
tree[max] = temp;
}
无序数列构建堆
/**
* 堆中某节点的子父节点的下标
* int child1 = i*2+1;//节点i的理论左子节点
* int child2 = i*2+2;//节点i的理论右子节点
* int parent = (i-1)~/2;//节点i的父节点
*/
buildHeap(List tree) {
int n = tree.length;
//找到最后一个节点的父节点 最后一个节点是n-1 ,父节点为((n-1)-1)/2 即n/2-1
for (int i = n ~/ 2 - 1; i >= 0; i--) {
heapify(tree, i, n);
}
}
堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:
大顶堆:每个结点的值都大于它的左右子结点的值,升序排序用大顶堆。
小顶堆:每个结点的值都小于它的左右子结点的值,降序排序用小顶堆。
排序流程
1.从原始数据集构建堆 - 从最后一个节点(n-1)
的父节点(i-1)/2
开始递减做heapify
2.把堆首和堆尾节点互换并摘除最末尾节点
3.堆大小-1并对堆首元素heapify
4.重复2,3步骤直到堆大小为1
Dart实现
main() {
var test = [4, 5, 6, 29, 3, 1, 7, 9];
heapSort(test);
print(test);//输出结果为[1, 3, 4, 5, 6, 7, 9, 29]
}
heapSort(List tree) {
int n = tree.length;
//构建堆
buildHeap(tree);
//从最后一个节点开始 交换堆首和堆尾节点互换
for (int i = n - 1; i >= 0; i--) {
swap(tree, 0, i);
//规整堆首节点 并将堆规模-1
heapify(tree, 0, i);
}
}
/**
* 堆中某节点的子父节点的下标
* int c1 = i*2+1;//节点i的理论左子节点
* int c2 = i*2+2;//节点i的理论右子节点
* int parent = (i-1)~/2;//节点i的父节点
*/
buildHeap(List tree) {
int n = tree.length;
//找到最后一个节点的父节点 以此开始直至堆首 规整每个节点 最后一个节点是n-1 ,父节点为((n-1)-1)/2 即n/2-1
for (int i = n ~/ 2 - 1; i >= 0; i--) {
heapify(tree, i, n);
}
}
/**
* tree
* i 要规整的节点
* n 节点总数
*/
heapify(List tree, int i, int n) {
//保证节点i与他的子节点符合堆定义 即节点i的值是最大的
int c1 = i * 2 + 1; //节点i的理论左子节点
int c2 = i * 2 + 2; //节点i的理论右子节点
int max = i;
if (c1 < n && tree[c1] > tree[max]) {
max = c1;
}
if (c2 < n && tree[c2] > tree[max]) {
max = c2;
}
if (max != i) {
swap(tree, i, max);
heapify(tree, max, n);
}
}
swap(List tree, int i, int max) {
int temp = tree[i];
tree[i] = tree[max];
tree[max] = temp;
}