算法导论堆排序的复习

首先建立一个最大堆或者最小堆,需要进行max-heapify,build-max-heap过程,这里的2个过程也是最最核心和重要的,堆排序和优先队列都是建立在此基础上的。好废话不多说,我们来看看他们都是怎么构造这些巧妙的结构的吧

  max-heapify过程,需要明确的是首先堆是个完全二叉树结构,而最大堆就是他的每个子树的父节点都比子节点要大,最小堆就刚好相反。max-heapify过程就是输入一个数组A和下标i,并且以i节点为父节点的左右子树都是最大堆,当A[i]可能小于其子女,也就是不符合最大堆的定义,我们要想办法调整整个数组结构使他符合定义。我们假定数组数组的左儿子节点为2×i,右儿子为2×i+1,事实上这样构造的二叉树刚刚好填满整个数组。算了下面的调整过程我用代码描述好了,文字太罗嗦,效果反而不好。

 void maxheapify(int A[],int  i,int heapsize)//最大堆
{
int strlen=heapsize;
int l,r;
l=2*i;
r=l+1;
int largest=i;
if(l<=strlen&&A[i]<A[l])//2个if找出左右子树的最大值然后与A[i]交换
{
  largest=l;
}
if(r<=strlen&&A[largest]<A[r])
{
    largest=r;
}
if(largest!=i)
{
    temp=A[i];
    A[i]=A[largest];
    A[largest]=temp;
    maxheapify(A,largest);//向下递归知道叶子节点
}

}

这个过程的时间复杂度是logn,也就是树的最大高度。

接下来是build-max-heap的过程,之所以在max-heapify之后才建立这个过程是因为,要用到前者来构建最大堆。好了我说一下实现的具体思路

首先给你一个无序的数组,教你把它构建出一个最大堆,你怎么办。。很容易想到2个思路,一个从根节点进行构建,一个是从叶节点进行构建。首先从根节点进行构建的话,很容易否定,因为他的左右子树也是无序状态,没有最大堆的结构。而从叶子节点构建的话,就刚好弥补了前面的。首先叶子节点本身是最大堆,因为他没有子树了。然后再利用前面maxheapify过程进行保持最大堆的性质。从叶节点的父节点开始不断维护直到根节点,就完成了最大堆的构建。下面是c++代码

void buildheap(int A[])
{
    for(int i=strlen(A)/2;i>=1;i--)
    {
        maxheapify(A,i,strlen(A);
    }
}

这个过程的中复杂度也是比较优秀的,貌似平均是n,直观上是nlogn,有了这个究可以进行堆排序了。只要你每次弹出最大堆的根节点,然后再进行一次维护久可以了,代码也是比较巧妙的。

heapsort(int A[])
{
  buildheap(A);
  int s=strlen(A);
  while(s>1)   //将最大数和堆中最后一个数交换,然后使堆的大小减少1,再进行维护。
  {
      int temp=A[1];
      A[1]=A[s];
      A[s]=temp;
      s--
      heapify(A,1,s);
  }
}

有点事先写到这儿吧。队列的插入什么的在晚些我会补回来

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值