堆排序和建立最大堆

堆是完全二叉树的结构,因此对于一个有n个节点的堆,高度为O(logn)。

最大堆:堆中的最大元素存放在根节点的位置。

除了根节点,其他每个节点的值最多与其父节点的值一样大。也就是任意一个子树中包含的所有节点的值都不大于树根节点的值。

堆中节点的位置编号都是确定的,根节点编号为1,每一层从左到右依次编号。由堆是完全二叉树,可以知道当堆中某个节点的编号为i时,如果这个节点有左右子树,那么左子树的节点编号为2*i,右子树的节点编号为2*i+1(当然这是在根节点编号为1的情况时)。

并且有n个节点的堆中叶子节点的编号为从n/2+1~n。因为假设节点n/2+1不是叶子节点,那么它的左子节点编号(n/2+1)*2=n+1,而节点总共只有n个。完全二叉树的叶子节点只出现在最下面两层。最下层的叶子集中在左边,倒数二层的叶子集中在右边。

维护最大堆函数MAX_HEAPWEIHU(A,i),假定节点i的左右子树已经是最大堆。那么维护堆时,先比较i节点的值与左右节点值的大小,将三个数中的最大值交换到根节点的位置。假设根节点i与左子节点的值交换了,那么左子树就要再次调用MAX_HEAPWEIHU(A,2*i),判断左子树还是不是最大堆,如果是则结束,否则继续调用进行维护。因此调用MAX_HEAPWEIHU(A,i)的时间复杂度为O(logn)。

heapfy(int a[],int i,int heapsize)
{
     int largest=i;
     int left=2*i-1;
     int right=2*i;
     if(left<heapsize && a[i]<a[left])
           largest=left;
     if(right<heapsize && a[largest]<a[right])
           largest=right;
     if(largest!=i)
     {
           swap(a[i],a[largest]);
           heapfy(a,largest);
     }
}

建立最大堆:将A[1,n]数组转换为最大堆。因为最大堆为完全二叉树结构,因此A[n/2+1],……,A[n]是最大堆的叶子节点。每个叶子节点本身就是一个最大堆,所以我们就要从A[n/2]~A[1]逐步维护这个最底层的最大堆(调用MAX_HEAPWEIHU(A,i)维护)。

void buildheap(int a[],int len)
{
      for(int i=len/2-1;i>=0;i--)
          heapfy(a,i,len);
}        

堆排序:先建立一个最大堆。然后将最大堆的A[1]与A[n]交换,然后从堆中去掉这个节点n,通过减少A.heap_size的值来实现。剩余的节点中,新的根节点可能违背了最大堆的性质,因此需要调用MAX_HEAPWEIHU(A,1)来维护最大堆。

void sortheap(int a[],int len)
{

    for(int i=n-1;i>=0;i--)
    {
         swap(a[0],a[i]);
         heapfy(a,0,i);
    }
}    
#include<iostream>
using namespace std;
void heapfy(int a[],int index,int heapsize)
{
    int left=index*2+1;
    int right=left+1;
    int largest=index;
    if(left<heapsize&&a[index]<a[left])
        largest=left;
    if(right<heapsize&&a[largest]<a[right])
        largest=right;
    if(largest!=index)
    {
        swap(a[index],a[largest]);
        heapfy(a,largest,heapsize);
    }
}
void heapsort(int a[],int len)
{
    for(int i=len/2-1;i>=0;i--)
    {
        heapfy(a,i,len);
    }
    for(int i=len-1;i>=0;i--)
    {
        swap(a[i],a[0]);
        heapfy(a,0,i);
    }
}
int main()
{
    int a[10]={9,3,4,5,1,8,0,2,7,6};
    heapsort(a,10);
}
时间: 2024-08-24 19:22:05

堆排序和建立最大堆的相关文章

歌词VSM实现!!!

主体VSM_SetUP.cpp; 1 /*[ar:歌词作者] 2 [ti:歌词(歌曲)的标题] 3 */ 4 //编写程序实现lrc(歌词) 文件的检索,检索模型要求采用向量空间模型.请将源程序和文档压缩后,一并上传. 5 #include<iostream> 6 7 #include"Document_Index.h" 8 9 using namespace std; 10 void main() { 11 cout << "*****本程序实现一个

最小/大堆的操作及堆排序

摘自:<啊哈算法> 我们要用1, 2, 5, 12, 7, 17, 25, 19, 36, 99, 22, 28, 46, 92来建立最小堆,并且删除最小的数,并增加一个数23 如何建立这个堆: //建堆 n = 0; for (int i = 1; i <= m; i++) { n++; h[n] = a[n]; shiftup(n); } 我们还有更快的方法可以建立一个堆 思路:直接把1, 2, 5, 12, 7, 17, 25, 19, 36, 99, 22, 28, 46, 92

【数据结构】排序番外篇 堆,堆排序与其前身选择排序

堆 优先队列:特殊的"队列",取出元素的顺序是依照元素的优先权(关键字)大小,而不是元素进入队列的先后顺序 堆是优先队列的完全二叉树表示. 堆的两个特性: ①结构性:用数组表示的完全二叉树 ②有序性:任意结点的关键字是其子树所有结点的最大值,叫最大堆(或最小值,叫最小堆)(注意从根结点到任意结点路径上结点序列的有序性) 下面举一个最大堆的例子. /** 最大堆的操作 */ typedef struct HeapStruct *MaxHeap; struct HeapStruct { E

利用堆实现堆排序&amp;优先队列

数据结构之(二叉)堆 一文末尾提到"利用堆可以实现:堆排序.优先队列".本文代码实现之. 1.堆排序 假设要将无序数组按非递减(递增)排序,则应使用大(小)顶堆.这里涉及到大堆排序涉及到三种操作:(1).MaxHeapify操作(自顶向下即SiftDown操作):(2).BuildMaxHeap操作(线性时间内将无序数组构造成一个最大堆):(3)将堆顶元素和堆的最后一个元素交换,并将堆元素大小减去1,对堆顶元素调用MaxHeapify操作重新调整为大顶堆,重复直到数组有序.下面是详细的

算法-java代码实现堆排序

堆排序 第7节 堆排序练习题 对于一个int数组,请编写一个堆排序算法,对数组元素排序. 给定一个int数组A及数组的大小n,请返回排序后的数组. 测试样例: [1,2,3,5,2,3],6 [1,2,2,3,3,5] Java (javac 1.7) 代码自动补全 1 import java.util.*; 2 3 public class HeapSort { 4 public int[] heapSort(int[] A, int n) { 5 int lastIndex = n - 1;

详谈排序算法之选择类排序(两种方法实现堆排序)

   今天我们再来讨论一下选择类排序,选择类排序分为:简单排序,树形选择排序和堆排序.但我们主要说的是简单和堆排序两个,因为树形选择排序使用了较多的辅助空间,以及和∞进行多余比较,为弥补树型选择排序的这些缺点, J.W.J.Williams 在 1964 年提出了进一步的改进方法,即堆排序.对于我个人而言..一开始并不是很理解它的算法思想,纠结了许久.在网上查找资料的时候发现这位大神的文章思路十分清晰,而且把创建堆以及堆化数组的算法讲解的十分详细.如果有不明白堆排序思路的,可以先看看这篇文章~堆

Chapter 6 堆排序

-------------------注明---------------- 以下内容来自于<算法导论>           lz新手,存在各种错误以及各种不合理的地方望大家指出 堆排序时间复杂度为O(nlgn),并且就有空间原址性:任何时候都只需常数个额外的元素空间存储临时数据 6.1 堆 堆是一个数组,但可以被看做近似的完全二叉树,树上的每个结点对应数组中的一个元素.除最底层外,该树是完全充满的! 实例(原书上的图): 可分为最大堆和最小堆,最大堆性质:A[parent(i)]≥A[i] -

排序算法之堆排序

1. 堆排序的思想 输入一个数组,利用一组二叉树的操作使其变成有序的数组,就是堆排序 堆排序利用的是二叉树的思想,操作对象是数组,所以数组需要在逻辑上映射到二叉树上,由于数组的下标是连续的,而二叉树中只有完全二叉树和满二叉树是连续的,所以将数组元素逐个映射到完全二叉树上,然后配备一系列的操作即可.例如数组data[]={9,6,5,4,3,2,1,7},映射到完全二叉树上如下图所示. 2.堆排序的过程 还是用上面的data数组作为输入数组,映射到完全二叉树如上图所示,怎么利用二叉树的性质,才能使

算法导论之 堆排序研究

参考文献1:算法导论第六章讲解 堆排序 参考文献2:<a target=_blank href="http://blog.csdn.net/xiaoxiaoxuewen/article/details/7570621">http://blog.csdn.net/xiaoxiaoxuewen/article/details/7570621</a> /**********************************************************