堆排序:
利用最大堆/最小堆完成排序
用数组存储,但逻辑结构为 完全二叉树
HeapElem arr[] = {45,23,56,34,12,45,67,78,90};
物理结构:
逻辑结构:
arr[end] = 90
start = (end-1)/2=3
tmp = 34
i = 3 (要调整的结点)
j= i*2+1 (左孩子结点)
对 3 7 8 进行判断,已符合最小堆规则 则不调整 break
arr[i] = tmp;
–pos // 开始循环调整 2位置的 while(pos>=0)
普通结构堆排序
#include <stdio.h>
#include <assert.h>
typedef int HeapElem ; // 定义堆排序时数据类型
template<class Type>
void Swap(Type &a,Type &b) // 交换函数
{
Type tmp = a;
a=b;
b=tmp;
}
void FileterDown(HeapElem *p,int start,int end) // 向下调整
{
int i = start; // 调整的分支结点 起始位置
int j = i*2 +1; // 左孩子
HeapElem tmp = p[i]; // 取出当前元素
while(j<=end) // 在end之前
{
if(j < end && p[j]>p[j+1]) j+=1; // 左右孩子内部判断取最小==》最小堆
if(tmp <= p[j]) break;
p[i] = p[j];
i = j; // 向下继续调整
j = i*2+1;
}
p[i] = tmp;
}
void MakeMinHeap(HeapElem *p ,int n)
{
if(p == NULL || n <2)
{
return ;
}
int end = n-1 ; // 找出最后一个结点下标
int pos = (end -1)/2; // pos为end的双亲结点
while(pos>=0)
{
FileterDown(p,pos,end); //向下调整
--pos; // 要调整的位置向上走
}
}
void Heap_sort(HeapElem *p,int n)
{
int pos = n-1;
while(pos > 0)
{
Swap(p[0],p[pos]); // 用堆顶最小元素 与末尾元素交换
FileterDown(p,0,--pos); // 继续调整剩余其他元素
}
}
void PrintHeap(HeapElem *p ,int n)
{
assert(p != NULL);
for(int i = 0;i<n;++i)
{
printf("%d ",p[i]); // 打印 从大到小
}
printf("\n");
}
void main()
{
HeapElem arr[] = {45,23,56,34,12,45,67,78,90};
int n = sizeof(arr)/sizeof(arr[0]);
MakeMinHeap(arr,n);
Heap_sort(arr,n);
PrintHeap(arr,n);
}
测试结果: