这里的堆其实是一种采用顺序存储的数据结构
且采用树型的表现形式(完全二叉树),至于完全二叉树以什么样的形式存储在数组中,请参考数据结构相关的书籍。下面直接给出完全二叉树中父结点与左右孩子的关系。
int record[1000];//存储二叉树所有结点的数组
int root;//某子树的一根结点
int Lchild=2*root;//record数组中,root的左孩子所在下标
int Rchild=2*root+1//record数组中,root的左孩子所在下标
对于大顶堆,父结点的值大于孩子结点的值。小顶堆,父结点的值小与孩子结点的值。采用堆排序的时间复杂度为O(nlgn),且为原址排序。
维护大顶堆O(lgn)
//维护子树,使其保持大顶堆的性质。递归维护
void MAX_HEAPIFY(int *a, int root,int len)
{
int l=2*root;
int r=l+1;
int largest=root;
//选择父结点,左右孩子结点中,值最大的结点,并用largest记录下表编号
if(l<len&&a[l]>a[root])
largest=l;
if(r<len&&a[r]>a[largest])
largest=r;
//不符合大顶堆的性质,向下递归修正
if(largest!=root)
{
int temp=a[root];
a[root]=a[largest];
a[largest]=temp;
MAX_HEAPIFY(a,largest,len);
}
}
建立大顶堆O(n)注意不是O(nlgn)推导过程很复杂
void BUILD_MAXHEAP(int *a,int len)
{
//自下而上,从叶子结点开始遍历二叉树,维护大顶堆
for(int i=len-1; i>=0; i--)
{
MAX_HEAPIFY(a,i,len);
}
}
对大顶堆排序(升序排列)O(nlgn)
void SORT_MAXHEAP(int *a,int len)
{
//每次取出堆顶元素与数组末尾元素交换,并将数组长度减一,维护大顶堆。最终得到升序排列的数组
while(len>1)
{
len--;
int temp=a[len];
a[len]=a[0];
a[0]=temp;
MAX_HEAPIFY(a,0,len);
}
MAX_HEAPIFY(a,0,1);
}
小顶堆维护O(lgn)
void MIN_HEAPIFY(int *a,int root,int len)
{
int l=2*root;
int r=l+1;
int smallest=root;
if(l<len&&a[l]<a[root])
smallest=l;
if(r<len&&a[r]<a[smallest])
smallest=r;
if(smallest!=root)
{
int temp=a[root];
a[root]=a[smallest];
a[smallest]=temp;
MIN_HEAPIFY(a,smallest,len);
}
}
小顶堆建立O(n)
void BUILD_MINHEAP(int *a,int len)
{
for(int i=len-1; i>=0; i--)
{
MIN_HEAPIFY(a,i,len);
}
}
小顶堆排序O(nlgn)
void SORT_MINHEAP(int *a,int len)
{
while(len>1)
{
len--;
int temp=a[len];
a[len]=a[0];
a[0]=temp;
MIN_HEAPIFY(a,0,len);
}
MIN_HEAPIFY(a,0,1);
}
我写的这些博客,也只是业余爱好,加深自己对知识的理解。现在网上的博客越来越多,鱼龙混杂。建议大家还是认真的去读书,尝试理解真正的大牛是怎么思考问题的。
本文介绍了堆排序这种基于完全二叉树的顺序存储数据结构。堆排序的时间复杂度为O(nlgn),分为大顶堆和小顶堆,分别适用于升序和降序排列。维护和建立堆的操作分别需要O(lgn)和O(n)时间,而排序过程则为O(nlgn)。作者强调理解算法背后的思维,并推荐通过阅读专业书籍来深入学习。
1769

被折叠的 条评论
为什么被折叠?



