算法导论堆排序的复习
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);
}
}
有点事先写到这儿吧。队列的插入什么的在晚些我会补回来
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);
}
}
有点事先写到这儿吧。队列的插入什么的在晚些我会补回来
相关文章推荐
- 算法导论第六章-堆排序
- 算法导论--堆排序(堆维护,建堆,堆排序)
- 算法导论第六章 堆排序
- 算法导论之插入排序,选择排序,归并排序,冒泡排序,希尔排序,堆排序,快速排序的c语言实现
- 算法导论堆排序python实现
- 算法导论 习题6.2-5 用迭代法实现堆排序
- 算法导论(第三版)-复习- K-colorful Path
- 《算法导论》7、堆排序实现(C++)
- 《算法导论》第6章 堆排序 (1)最大堆与堆排序
- 算法导论学习之——堆排序
- 面试复习(C++)之堆排序
- 《数据结构与算法分析:C语言描述》复习——第六章“排序”——堆排序
- 《算法导论》读书笔记--堆排序
- 算法导论之堆排序
- 《算法导论》学习心得(四)—— 堆排序(Java)
- 复习数据结构:排序算法(六)——堆排序
- 算法导论 习题6.2-5 用迭代法实现堆排序
- 算法导论(第三版)-复习16贪心算法
- 老老实实复习算法: 4 堆排序
- 跟着《算法导论》学习——堆排序