郭郭自学笔记(1):堆排序1.0
1.堆是什么:堆其实就是一个完全二叉树
特点:
-
父结点的键值都比他的子结点键值大,或者父结点键值都比他的子结点键值小,前者称之为大根堆,后者称之小根堆。
-
堆中任一子树亦是堆。
例如下图(大根堆):
2.堆特性的应用
对于给的一组数据,如上图(16,14,10,8,7,9,3,2,4,1),从大到小排序。
如上图,一个大根堆,的根节点,明显是一组数据的最大值。
-
首先我们将这组数据存储在一个一维数组里,把它当成一棵以1号元素为根节点,第n个元素的左孩子就是2n,右孩子就是2n+1(假如这个元素有孩子的话)的完全二叉树。
现在该想想怎么把这个完全二叉树变成堆了? -
因为大根堆的父结点的键值都比他的子结点的键值大,所以我们将一个结点的键值与他的左右孩子的键值比较,如果有孩子的键值比它大,我们就进行交换,如果两个孩子的键值都比它大,我们选择数值大进行交换。然后,在比较交换后,该元素与他的新的孩子进行比较,直到,不满足交换条件,或没有孩子。按此方法对1-n元素进行调整,便可以得到令我们满意的堆了。
下面我们进行排序了。
-
输出根结点,输出后与交换最后一个元素,将对元素个数减一,调整堆,新堆执行同样操作,直至排序完成。
3.堆排序代码(C++,下次我绝对不写这么多话了,直接上代码)
#include <iostream>
#include <cstdlib>
using namespace std;
#define MAX 1000
int elem[MAX];
int n;
//交换两个元素
void Swap(int i, int j)
{
elem[i] = elem[i] ^ elem[j];
elem[j] = elem[i] ^ elem[j];
elem[i] = elem[i] ^ elem[j];
}
//调整元素位置
void AdjustHeap(int i)
{
bool over = false;
int temp;
while (2 * i <= n && !over)
{
if (elem[i] <elem[2 * i])
{
temp = 2 * i;
}
else
{
temp = i;
}
if (2 * i + 1 <= n&&elem[temp] < elem[2 * i + 1])
{
temp = 2 * i + 1;
}
if (i != temp)
{
Swap(i, temp);
i = temp;
}
else
{
over = true;
}
}
}
//建堆
void CreateHeap()
{
for (int i = n / 2; i >= 1; i--)
{
AdjustHeap(i);
}
}
//删除元素
int DeleteElem()
{
int temp = elem[1];
elem[1] = elem[n];
n--;
AdjustHeap(1);
return temp;
}
int main()
{
int num;
std::cin >> num;
n = num;
for (int i = 1; i= n; i++)
std::cin >> elem[i];
CreateHeap();
for(int i = 1;i<=num;i++
)
std::cout << DeleteElem() << " ";
std::cout << endl;
system("pause");
}
自学笔记,如有错误,请留言。