堆排序
2017-08-11 19:59
726 查看
假设有序列:K1,K2,...Kn
1、如果满足:Ki>=K2i且Ki>=K2i+1,则称这个序列为大根堆。
2、如果满足:Ki<=K2i且Ki<=K2i+1,则称这个序列为小根堆。
大根堆排序的大致流程如下:
整个过程在数组中进行操作,交换堆顶元素和最后一个元素就是交换数组中的第一个元素与最后一个元素。
假设有数组a[0]a[1]a[2]…a[n-1](大根堆),交换后成为a[n-1]a[1]a[2]…a[0]。从而形成新序列a[n-1]a[1]a[2]…a[n-2],对这个新序列再进行调整、交换。
一共会产生n-1个新序列。
最外层循环:
for(j=n-1;j>0;j--){};
注:去掉的部分为有序元素,不参与后面的排序。实际上在排序过程中原数组的长度是不变的。
j=0:
j=1:
j=2:
...
j=8:
数组中的元素看成是完全二叉树。
大根堆调整: HeapAdjust(int low,int high)
假设有以下数据:
写成完全二叉树如下:
先将这个完全二叉树的局部(根节点、左子树、右子树)调整成大根堆:
锁定要排序的元素,会有2种情况:(i为对应数组的下标)
上面的完全二叉树属于第1种情况,
共9个数,a[0]~a[8]。
low=0,high=8.
i分别取:8,6,4,2
再假设共10个数,a[0]~a[9],此时属于第2种情况,
low=0,high=9
i分别取:9,8,6,4,2
怎么区分这两种情况?
if(i%2==0)//第一种情况
if(i%2==1)//第二种情况
调整成大根堆:
if(i%2==0)
{
for(i=high;i>=2;i-=2)
{
if(a[(i-2)/2]<a[i-1])
{
temp=a[i-1];
a[i-1]=a[(i-2)/2];
a[(i-2)/2]=temp;
}
if(a[(i-2)/2])<a[i])
{
temp=a[i];
a[i]=a[(i-2)/2];
a[(i-2)/2]=temp;
}
}
}
if(i%2==1)
{
if(a[(high-1)/2]<a[high])
{
temp=a[high];
a[high]=a[(high-1)/2];
a[(high-1)/2]=temp;
}
for(i=high-1;i>=2;i-=2)
{
if(a[(i-2)/2]<a[i-1])
{
temp=a[i-1];
a[i-1]=a[(i-2)/2];
a[(i-2)/2]=temp;
}
if(a[(i-2)/2])<a[i])
{
temp=a[i];
a[i]=a[(i-2)/2];
a[(i-2)/2]=temp;
}
}
}
交换大根堆中的堆顶元素和最后一个元素:
temp=a[0];
a[0]=a[j];
a[j]=temp;
最后套上最外层循环。
1、如果满足:Ki>=K2i且Ki>=K2i+1,则称这个序列为大根堆。
2、如果满足:Ki<=K2i且Ki<=K2i+1,则称这个序列为小根堆。
大根堆排序的大致流程如下:
整个过程在数组中进行操作,交换堆顶元素和最后一个元素就是交换数组中的第一个元素与最后一个元素。
假设有数组a[0]a[1]a[2]…a[n-1](大根堆),交换后成为a[n-1]a[1]a[2]…a[0]。从而形成新序列a[n-1]a[1]a[2]…a[n-2],对这个新序列再进行调整、交换。
一共会产生n-1个新序列。
最外层循环:
for(j=n-1;j>0;j--){};
注:去掉的部分为有序元素,不参与后面的排序。实际上在排序过程中原数组的长度是不变的。
j=0:
j=1:
j=2:
...
j=8:
数组中的元素看成是完全二叉树。
大根堆调整: HeapAdjust(int low,int high)
假设有以下数据:
写成完全二叉树如下:
先将这个完全二叉树的局部(根节点、左子树、右子树)调整成大根堆:
锁定要排序的元素,会有2种情况:(i为对应数组的下标)
上面的完全二叉树属于第1种情况,
共9个数,a[0]~a[8]。
low=0,high=8.
i分别取:8,6,4,2
再假设共10个数,a[0]~a[9],此时属于第2种情况,
low=0,high=9
i分别取:9,8,6,4,2
怎么区分这两种情况?
if(i%2==0)//第一种情况
if(i%2==1)//第二种情况
调整成大根堆:
if(i%2==0)
{
for(i=high;i>=2;i-=2)
{
if(a[(i-2)/2]<a[i-1])
{
temp=a[i-1];
a[i-1]=a[(i-2)/2];
a[(i-2)/2]=temp;
}
if(a[(i-2)/2])<a[i])
{
temp=a[i];
a[i]=a[(i-2)/2];
a[(i-2)/2]=temp;
}
}
}
if(i%2==1)
{
if(a[(high-1)/2]<a[high])
{
temp=a[high];
a[high]=a[(high-1)/2];
a[(high-1)/2]=temp;
}
for(i=high-1;i>=2;i-=2)
{
if(a[(i-2)/2]<a[i-1])
{
temp=a[i-1];
a[i-1]=a[(i-2)/2];
a[(i-2)/2]=temp;
}
if(a[(i-2)/2])<a[i])
{
temp=a[i];
a[i]=a[(i-2)/2];
a[(i-2)/2]=temp;
}
}
}
交换大根堆中的堆顶元素和最后一个元素:
temp=a[0];
a[0]=a[j];
a[j]=temp;
最后套上最外层循环。
相关文章推荐
- 堆排序
- 选择排序:简单选择排序、堆排序
- C语言实现 排序源程序(包括直接插入、希尔、冒泡、快速、简单选择、堆排序)
- java实现堆排序
- 算法导论排序算法之堆排序(五)
- 算法(2)堆排序
- 堆排序 [Algorithm]
- 堆--堆排序--heap--heap_sort
- 算法导论 习题6.2-5 用迭代法实现堆排序
- 第14周项目1(6)- 验证算法 堆排序
- 堆排序(模板)
- 详解数组实现隐式二叉堆及堆排序
- 数据结构之排序——堆排序
- c++实现堆排序及运行实例结果
- 算法熟记-排序系列-堆排序
- 排序算法合集(插入排序,折半插入排序,希尔排序,冒泡排序,快速排序,简单选择排序,堆排序,归并排序)
- 堆排序
- 排序算法(二)--堆排序(JAVA)
- 堆排序
- 堆排序