1.堆
堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于等于其左右孩子结点的值,称为小顶堆!
2.堆排序
堆排序算法就是利用堆(小顶堆或者大顶堆)进行排序的方法。将待排序的序列构造成一个大顶堆,此时整个序列的最大值就是根节点。将它移走(跟堆的最后一个元素交换,此时末尾元素就是最大值),然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次小值。如此反复执行,便能得到一个有序序列了。
3. 代码实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _505_堆排序_顺序存储
{
class Program
{
static void Main(string[] args)
{
int[] data = { 50, 10, 90, 30, 70, 40, 80, 60, 20 };
HeapSort(data);
foreach(int i in data)
{
Console.Write(i + " ");
}
Console.ReadKey();
}
public static void HeapSort(int[] data)
{
for(int i=data.Length/2;i>=1;i--)//遍历这个树的非叶结点,把所有的子树变成大顶堆
{
HeapAjust(i, data, data.Length);
}
for(int i=data.Length;i>1;i--)
{
//把编号1和编号i位置进行交换
//1到(i-1)构造成大顶堆
int temp1 = data[0];
data[0] = data[i - 1];
data[i - 1] = temp1;
HeapAjust(1, data, i - 1);
}
}
private static void HeapAjust(int numberToAjust,int[] data,int maxNumber)
{
int maxNodeNumber = numberToAjust;//最大结点的编号
int iTemp = numberToAjust;
while (true)
{
//把i结点的子树变成大顶堆
int leftChildNumber = 2 * iTemp;
int rightChildNumber = leftChildNumber + 1;
if (leftChildNumber <= maxNumber && data[leftChildNumber - 1] > data[maxNodeNumber - 1])
{
maxNodeNumber = leftChildNumber;
}
if (rightChildNumber <= maxNumber && data[rightChildNumber - 1] > data[maxNodeNumber - 1])
{
maxNodeNumber = rightChildNumber;
}
if (maxNodeNumber != iTemp)//发现了一个比i更大的子节点,交换i好maxNodeNumber里面的数据
{
int temp = data[iTemp - 1];
data[iTemp - 1] = data[maxNodeNumber - 1];
data[maxNodeNumber - 1] = temp;
iTemp = maxNodeNumber;
}
else
{
break;
}
}
}
}
}