一、堆排序算法介绍
堆是一种特殊的树形数据结构,其每个结点都有一个值,通常提到的堆都是指一棵完全二叉树,根结点的值小于(或大于)两个子结点的值,同时,根结点的两棵子树也分别是-个堆。堆排序是一种树形选择排序,在排序过程中,将R[...n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结 点和孩子结之间的内在关系来选择最小的元素。
堆一般分为大顶堆和小顶堆两种不同的类型。对于给定n个记录的序列(r(1), r(2), ... r(n)),当且仅当满足条件(r(i)≥r(2i)&&r()≥r(2i+1), i=1,2, ..). 时称之为大顶堆,此时,堆顶元素必为最大值。对于给定n个记录的例(()(2)...n)). 当且仅当满足条件(r(i)≤r(2i)&&r()≤r(2i+1),
i=1,2...n)时称之为小顶堆,此时,堆顶元素必为最小值。
堆排序的思想是对于给定的n个记录,初始时把这些记录看作-棵顺序存储的_ -叉树,然后将其调整为-一个大顶堆,再将堆的最后一个元素 与堆顶元素. (即二叉树的根结点)进行交换后,堆的最后- -个元素即为最大记录;接着将前(n-1) 个元素(即不包括最大记录)重新调整为一个大顶堆,再将堆顶元素与当前堆的最后-个元素进行交换后得到次大的记录,重复该过程直到调整的堆中只剩一个元素时为止,该远素即为最小记录,此时可得到一个有序序列。
二、堆排序过程:
1)将初始待排关键字序列(R1, R2...Rn) 构建成大顶堆,此堆为初始
的无区;
2)将堆顶元素R[1]与最后- -个元素R[n]交换,此时得到新的无序区
(R1, R2, ..Rn-1)和新的有序区(Rn), 且满足R[1, 2..n-1]sR[n];
3)由于交换后新的堆顶R[1]可能违反堆的性质,因此
需要对当前无序.
区(R1, R2,..-1)调整为新堆,然后再次将R[1]与无序区最后- 个元
素交换,得到新的无区(R1, R...n-2)和新的有序区(Rn-1, Rn)。
不断重复此过程直到有序区的元素个数为(n-1), 则整个排序过程完成。
三、堆排序算法代码:
function heapSort(arr)
{
var heapSize = arr.length;
var temp;
// 建堆
for(var i=Math.floor(heapSize/2)-1;i>=0;i--)
{
console.log("建堆");
console.log("i:"+i);
// for(let j=0;j<arr.length;j++)
// {
// console.log("arr["+j+"] ="+arr[j]);
// }
heapify(arr,i,heapSize);
}
// 堆排序
for(var j=heapSize-1;j>=1;j--)
{
console.log("堆排序");
temp=arr[0];
arr[0]= arr[j];
arr[j] = temp;
// for(let j=0;j<arr.length;j++)
// {
// console.log("arr["+j+"] ="+arr[j]);
// }
heapify(arr,0,--heapSize);
}
return arr;
}
/**
* @param arr 数组
* @param x 数组下标
* @param len 堆大小
*/
function heapify(arr,x,len)
{
var l = 2*x+1;
var r = 2*x+2;
var largset = x;
var temp;
if(l<len&&arr[l]>arr[largset])
{
largset =l;
}
if(r<len&&arr[r]>arr[largset])
{
largset=r;
}
console.log("L:"+l);
console.log("R:"+r);
console.log("x:",x);
console.log("largset:"+largset);
if(largset!=x)
{
temp = arr[x];
arr[x] = arr[largset];
arr[largset] = temp;
// for(let j=0;j<arr.length;j++)
// {
// console.log("arr["+j+"] ="+arr[j]);
// }
heapify(arr,largset,len);
}
}
PS:其中注释部分,可以反注释来看其“大顶堆”的建立过程和堆的排序过程 。
四、测试代码:
var arr = [0,5,7,9,3,5,4];
var b = heapSort(arr);
console.log(b);
五、测试结果:
六、总结:
对于堆建立的过程,其主要是,首先,要选出“大项堆”,然后然后其最大的数放在最后的位置,之后再重新建立一个新的“大项堆”,然后再和(len--)进行交换。