现在的位置: 首页 > 综合 > 正文

堆排序

2013年11月18日 ⁄ 综合 ⁄ 共 1568字 ⁄ 字号 评论关闭

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;
}

抱歉!评论已关闭.