堆排序
2008-07-15 17:11
127 查看
http://www.inf.fh-flensburg.de/lang/algorithmen/sortieren/heap/heapen.htm(比较好的参考资料)
1、 堆排序定义
n个关键字序列Kl,K2,…,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质):
(1) ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤
)
若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。
2、大根堆和小根堆
根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最小者的堆称为小根堆。
根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最大者,称为大根堆。
注意:
①堆中任一子树亦是堆。
②以上讨论的堆实际上是二叉堆(Binary Heap),类似地可定义k叉堆。
3、堆排序特点
堆排序(HeapSort)是一树形选择排序。
堆排序的特点是:在排序过程中,将R[l..n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系【参见二叉树的顺序存储结构】,在当前无序区中选择关键字最大(或最小)的记录。
4、堆排序与直接插入排序的区别
直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。
堆排序可通过树形结构保存部分比较结果,可减少比较次数。
下面是我实现的堆排序
#include <stdio.h>
char buf[20];
//随机生成数组
void ran(int *a)
{
for(int i = 0; i < 12; i++)
a[i] = rand() % 100;;
}
//打印
void print(int *a)
{
sprintf(buf,"%18d/n",a[0]);
puts(buf);
sprintf(buf,"%10d%16d/n",a[1],a[2]);
puts(buf);
sprintf(buf,"%6d%8d%8d%8d/n",a[3],a[4],a[5],a[6]);
puts(buf);
sprintf(buf,"%4d%4d%4d%4d%4d/n",a[7],a[8],a[9],a[10],a[11]);
puts(buf);
}
//建堆
void heaps(int *a,int n)
{
int id,val;
id = val = 0;
for(int i = n/2; i >= 0; i--)
{
id = 2*(i+1);
--id;
if(id > n) continue;
if(id+1 <= n)
{
if(a[id] < a[id+1]) id++;
}
if(a[id] < a[i]) continue;
val = a[id];
a[id] = a[i];
a[i] = val;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int v;
int a[12];
ran(a);
puts("堆排序/n建堆:");
print(a);
heaps(a,11);
print(a);
for(int i = 1; i < 12; i++)
{
v = a[0];
a[0] = a[12-i];
a[12-i] = v;
heaps(a,11-i);
print(a);
}
char cc = getchar();
return 0;
}
1、 堆排序定义
n个关键字序列Kl,K2,…,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质):
(1) ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤
)
若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。
2、大根堆和小根堆
根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最小者的堆称为小根堆。
根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最大者,称为大根堆。
注意:
①堆中任一子树亦是堆。
②以上讨论的堆实际上是二叉堆(Binary Heap),类似地可定义k叉堆。
3、堆排序特点
堆排序(HeapSort)是一树形选择排序。
堆排序的特点是:在排序过程中,将R[l..n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系【参见二叉树的顺序存储结构】,在当前无序区中选择关键字最大(或最小)的记录。
4、堆排序与直接插入排序的区别
直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。
堆排序可通过树形结构保存部分比较结果,可减少比较次数。
下面是我实现的堆排序
#include <stdio.h>
char buf[20];
//随机生成数组
void ran(int *a)
{
for(int i = 0; i < 12; i++)
a[i] = rand() % 100;;
}
//打印
void print(int *a)
{
sprintf(buf,"%18d/n",a[0]);
puts(buf);
sprintf(buf,"%10d%16d/n",a[1],a[2]);
puts(buf);
sprintf(buf,"%6d%8d%8d%8d/n",a[3],a[4],a[5],a[6]);
puts(buf);
sprintf(buf,"%4d%4d%4d%4d%4d/n",a[7],a[8],a[9],a[10],a[11]);
puts(buf);
}
//建堆
void heaps(int *a,int n)
{
int id,val;
id = val = 0;
for(int i = n/2; i >= 0; i--)
{
id = 2*(i+1);
--id;
if(id > n) continue;
if(id+1 <= n)
{
if(a[id] < a[id+1]) id++;
}
if(a[id] < a[i]) continue;
val = a[id];
a[id] = a[i];
a[i] = val;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int v;
int a[12];
ran(a);
puts("堆排序/n建堆:");
print(a);
heaps(a,11);
print(a);
for(int i = 1; i < 12; i++)
{
v = a[0];
a[0] = a[12-i];
a[12-i] = v;
heaps(a,11-i);
print(a);
}
char cc = getchar();
return 0;
}
相关文章推荐
- [Unity][Heap sort]用Unity动态演示堆排序的过程(How Heap Sort Works)
- 排序——堆排序
- Go语言用堆排序的方法进行一千万个int随机数排序.
- java实现堆排序
- 堆排序
- 堆排序(Java实现)
- 算法复习之堆排序
- 堆排序
- 四、堆排序
- 序列——堆排序-大根堆(堆大顶)
- 堆排序(算法导论)
- 堆排序
- 快排与堆排序、归并排序的比较
- 堆与堆排序
- 各种常见的排序,冒泡排序,选择排序,插入排序,希尔排序,堆排序,快速排序,基数排序,桶排序
- 经典排序算法 -----冒泡排序,插入排序,快速排序,归并排序,堆排序
- 建堆,以及对堆排序
- HeapSort 堆排序 基于伪代码实现
- 数据结构学习笔记5-寻找最小的k个数(选择排序和堆排序)
- 堆排序