您的位置:首页 > 其它

算法导论堆排序的复习

2014-04-10 16:04 218 查看
首先建立一个最大堆或者最小堆,需要进行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);

  }

}

有点事先写到这儿吧。队列的插入什么的在晚些我会补回来
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: