基础知识:
堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。
堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图:
完全二叉树的特点:
已知当前节点的序号,能找出其父节点和左右孩子节点的序号。
堆排序的过程:
- 构建一个堆结构
- 每次把堆顶的元素和堆的最后一个元素交换,然后去除最后一个元素,这样又构成了一个堆结构。
- 重复1,2 过程。
如何构建一个堆 ( heapify的过程)
对于完全二叉树可以用一维数组来表示这棵完全二叉树,而完全二叉树又有它的特点,即根据当前节点可以找到左右孩子节点,也可以根据当前节点找到父节点。
指定任意一个节点的序列号i, 进行堆结构的过程:
void heapify(int tree[], int n, int i)
{
if(i>=n)
{
return;
}
int child1 = 2*i+1;
int child2 = 2*i+2;
int max = i;
if(child1 < n && tree[child1] > tree[max])
{
max = child1;
}
if(child2 < n && tree[child2] > tree[max])
{
max = child2;
}
if(i!=max)
{
swap_node(tree, max, i);
heapify(tree, n, max);
}
}
对于任何一个无序的数组,我们可以从底向上构建堆结构。因为节点的个数就是最后一个节点的序号,这样我们就知道了最后一个父节点的序号,如下图所示:
然后就可以整体构建堆结构了:
void build_heap(int tree[], int n)
{
int last_node = n-1;
int parent = (last_node-1)/2;
int i;
for(i = parent;i>=0;i--)
{
heapify(tree,n,i);
}
}
构建堆结构的整体过程:
//
// Created by 彭程明 on 2019/6/20.
//
#include <iostream>
using namespace std;
void swap_node(int arr[], int i,int j)
{
int temp;
temp = arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
void heapify(int tree[], int n, int i)
{
int child1 = 2*i+1;
int child2 = 2*i+2;
int max = i;
if(child1 < n && tree[child1] > tree[max])
{
max = child1;
}
if(child2 < n && tree[child2] > tree[max])
{
max = child2;
}
if(i!=max)
{
swap_node(tree, max, i);
//cout<<max<<endl;
heapify(tree, n, max);
}
}
void build_heap(int tree[], int n)
{
int last_node = n-1;
int parent = (last_node-1)/2;
int i;
for(i = parent;i>=0;i--)
{
heapify(tree,n,i);
}
}
int main()
{
int tree[] = {2, 5, 3, 1, 10, 4 };
int n = 6;
// heapify(tree, n, 0);
build_heap(tree, n);
for (int i = 0;i<n;i++)
{
cout<<tree[i]<<endl;
}
return 0;
}
现在堆结构构建好了,我们就可以排序了,把每次堆顶的和堆结构的最后一个元素交换位置,然后再移除最后一个元素。
最后进行排序就好了
void heap_sort(int tree[], int n)
{
build_heap(tree, n);
for(int i=n-1;i>=0;i--)
{
swap_node(tree,i,0);
// build_heap(tree, i);
heapify(tree,i, 0);
}
}
综上,堆排序整体代码如下:
//
// Created by 彭程明 on 2019/6/20.
//
#include <iostream>
using namespace std;
void swap_node(int arr[], int i,int j)
{
int temp;
temp = arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
void heapify(int tree[], int n, int i)
{
if(i>=n)
{
return;
}
int child1 = 2*i+1;
int child2 = 2*i+2;
int max = i;
if(child1 < n && tree[child1] > tree[max])
{
max = child1;
}
if(child2 < n && tree[child2] > tree[max])
{
max = child2;
}
if(i!=max)
{
swap_node(tree, max, i);
//cout<<max<<endl;
heapify(tree, n, max);
}
}
void build_heap(int tree[], int n)
{
int last_node = n-1;
int parent = (last_node-1)/2;
int i;
for(i = parent;i>=0;i--)
{
heapify(tree,n,i);
}
}
void heap_sort(int tree[], int n)
{
build_heap(tree, n);
for(int i=n-1;i>=0;i--)
{
swap_node(tree,i,0);
// build_heap(tree, i);
heapify(tree,i, 0);
}
}
int main()
{
int tree[] = {1, 2, 3, 4, 5, 6};
int n = 6;
// heapify(tree, n, 0);
heap_sort(tree, n);
for (int i = 0;i<n;i++)
{
cout<<tree[i]<<endl;
}
return 0;
}
JavaScript代码实现:
function swap_node(tree, i, max) {
let t = tree[i]
tree[i] = tree[max]
tree[max] = t;
}
function heapify(tree, n, i) {
// let len = tree.length - 1
if (i >= n) {
return
}
let child1 = 2 * i + 1
let child2 = 2 * i + 2;
let max = i
if (child1 < n && tree[max] < tree[child1]) {
max = child1
}
if (child2 < n && tree[max] < tree[child2]) {
max = child2
}
if (i != max) {
swap_node(tree, i, max)
heapify(tree, n, max)
}
}
function build_heap(tree) {
//找到父结点
let last_node = tree.length - 1;
let parent = parseInt((last_node - 1) / 2)
for (let i = parent; i >= 0; i--) {
heapify(tree, tree.length, i);
}
}
function heap_sort(tree) {
build_heap(tree)
for (let i = tree.length - 1; i >= 0; i--) {
swap_node(tree, i, 0);
heapify(tree, i, 0)
}
}
let arr = [3, 4, 2, 10, 100, 0]
heap_sort(arr)
console.log(arr)
python3 实现:
def heapify(tree, n, i):
if i >= n:
return
child1 = 2 * i + 1
child2 = 2 * i + 2
max = i
if child1 < n and tree[max] < tree[child1]:
max = child1
if child2 < n and tree[max] < tree[child2]:
max = child2
if max != i:
tree[i], tree[max] = tree[max], tree[i]
heapify(tree, n, max)
def build_heap(tree):
n = len(tree)
last_node = n - 1
parent = (last_node - 1) // 2
for i in range(parent, -1, -1):
heapify(tree, n, i)
def heap_sort(tree):
n = len(tree)
build_heap(tree)
for i in range(n - 1, 0, -1):
tree[i], tree[0] = tree[0], tree[i]
heapify(tree, i, 0)
arr = [1, 3, 4, 2, 5]
heap_sort(arr)
print(arr)
参考链接: https://www.bilibili.com/video/av47196993?from=search&seid=7155093278298159299