堆排序算法的实现
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆排序算法的实现相关的知识,希望对你有一定的参考价值。
n个关键字序列Kl,K2,…,Kn称为(Heap),当且仅当该序列满足如下性质(简称为堆性质):
(1) ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤ n)
若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。 (即如果按照线性存储该树,可得到一个不下降序列或不上升序列)。
本课程设计中主要完成以下内容:
1.设计堆排序算法并实现该算法。
2.对堆排序的时间复杂度及空间复杂度进行计算与探讨。
3.寻找改进堆排序的方法。
基本要求如下:
1.程序设计界面友好;2.设计思想阐述清晰;3.算法流程图正确;4.软件测试方案合理、有效。
#include<malloc.h>
#include<time.h>
#define LISTSIZE 100
#define MORESIZE 100
#define overflow -1
typedef struct
int data;
int fre;
Cell;
typedef struct
Cell *elem;
long int length;
unsigned long int count1;
unsigned long int count2;
long int listsize;
SqList;
SqList L1;
clock_t start,end;
FILE *p,*w;
int main (void)
void assign(Cell *a,Cell *b);
int LT(int a,int b);
void HeapSort (SqList &H);
void HeapAdjust (SqList &H,int s , int m);
void exchange(Cell *a,Cell *b);
//读入
int time=0;
while(time<4)
switch (time)
case 0:
p=fopen("data01.txt","r");
w=fopen("sorted01.txt","w");
break;
case 1:
p=fopen("data02.txt","r");
w=fopen("sorted02.txt","w");
break;
case 2:
p=fopen("data03.txt","r");
w=fopen("sorted03.txt","w");
break;
case 3:
p=fopen("data04.txt","r");
w=fopen("sorted04.txt","w");
break;
L1.count1=0;
L1.count2=0;
time++;
L1.elem=(Cell *)malloc((LISTSIZE+1)*sizeof(Cell));
L1.listsize=LISTSIZE;
L1.length=1;
Cell *newbase;
while(!feof(p))
if (L1.length>L1.listsize)
newbase=(Cell *)realloc(L1.elem,(L1.listsize+MORESIZE+1)*sizeof(Cell));
if (!newbase)
return overflow;
L1.elem=newbase;
L1.listsize+=MORESIZE;
fscanf (p,"%d (%d)\\n",&((L1.elem+L1.length)->data),&((L1.elem+L1.length)->fre));
L1.length++;
L1.length--;
printf ("listsize=%d length=%d\\n",L1.listsize,L1.length);
//排序
start=clock();//开始计时
HeapSort(L1); //堆排序
end=clock(); //结束计时
printf ("Time: %lf\\n",(double)(end-start)/CLOCKS_PER_SEC);//输出时间
for (int i=1;i<L1.length+1;++i)
fprintf (w,"%d (%d)\\n",(L1.elem+i)->data,(L1.elem+i)->fre);
fprintf (w,"比较次数%u,移动次数%u\\n",L1.count1,L1.count2);
printf ("比较次数%u,移动次数%u\\n",L1.count1,L1.count2);
fprintf (w,"Copyright Reserved,Cheng Xuntao,NWPU");
fclose(p);
fclose(w);
return 0;
int LT(int a,int b)//比较函数
L1.count1++;<br/> if (a<b)<br/> <br/> return 1;
else return 0;
void assign(Cell *a,Cell *b)//赋值函数
a->data=b->data;
a->fre=b->fre;
L1.count2++;
void exchange(Cell *a,Cell *b)//交换记录
int temp;
temp=a->data;
a->data=b->data;
b->data=temp;
temp=a->fre;
a->fre=b->fre;
b->fre=temp;
L1.count2+=3; //+=3
void HeapAdjust (SqList &H,int s , int m)//调节其成为堆
Cell *rc;
rc=(Cell *)malloc(sizeof(Cell));
int j;
assign(rc,H.elem+s); //暂存
for (j=2*s;j<=m;j*=2) //沿值较大的孩子节点向下筛选
if (j<m && LT((H.elem+j)->data,(H.elem+j+1)->data ))
j++; //j为值较大的记录的下标
if (!LT(rc->data,(H.elem+j)->data))
break; //rc应插入在位置s上
assign((H.elem+s),(H.elem+j));
s=j;
assign((H.elem+s),rc); //插入
//HeapAdjust
void HeapSort (SqList &H) //堆排序
int i;
for (i=H.length/2;i>0;--i) //把L.elem[1...H.length]建成堆
HeapAdjust(H,i,H.length);
for (i=H.length;i>1;--i)
exchange(H.elem+1,H.elem+i); //将堆顶记录和当前未经排序的子序列L.elem[i...i]中最后一个记录相互交换
HeapAdjust(H,1,i-1); //重新调整其为堆
//HeapSort 参考技术A #include <stdio.h>
void adjust(int *list,const int root,const int n);
void HeapSort(int *list,const int n)
int i=0;
for(i=n/2;i>=1;i--)
adjust(list,i-1,n);
int t=list[n];
list[n]=list[0];
list[0]=t;
if(n>1)
HeapSort(list,n-1);
else
int t=list[1];
list[1]=list[0];
list[0]=t;
void adjust(int *list,const int root,const int n)
int e=list[root];
int k=e,j=0;
for(j=2*root;j<=n;j*=2)
if(j<n)
if(list[j]<list[j+1])
j++;
if(k>=list[j])
break;
list[j/2]=list[j];
list[j/2]=e;
int main(int argc,char **argv)
int i=0;
int src[10]=26,5,77,1,61,11,59,15,48,19;
HeapSort(src,9);
i=0;
while(i<10)
printf("%d,",src[i]);
i++;
排序算法:堆排序-Java实现
排序算法(二):堆排序-Java实现
首先对堆排序有个整体的认识,堆排序是一个不稳定的排序算法,其平均时间复杂度为O(nlogn),空间复杂度O(1)。
那么何为堆排序呢?所谓堆排序是借助于堆的概念来完成的排序算法,其是选择排序中的一种,因此通过选择排序来理解堆排序会更加容易一些
下面我们来看一下堆的概念,其实堆又是借助于二叉树的概念来定义,对于堆分为大顶堆和小顶堆两种,下面用数学表示式来精确的描述如下:
假设我们使用array数组来存储堆,因为大顶堆表述为 array[i] >=array[2*i+1] && array[i] >= array[2*1+2] , 小顶堆表示为array[i] <=array[2*i+1] && array[i] <= array[2*1+2], 但是值的注意的是array[2*i+1] 与array[2*i+2] 之间没有大小约束关系
对于堆的基本定义我们已经很清晰了,下面我们将详细的介绍一下堆排序的思路
堆排序的整体思路如下(以大顶堆为例说明,小顶堆同理哈)
- 根据大定堆的概念array[0]始终是最大的,因此与array[array.length-1]进行交换,此时就形成了 array[0].... array[array.length-2] 的无序数组和 array[array.length-1] 的有序数组
- 在1中形成的 array[0].... array[array.length-2] 无序数组中破坏了堆的特性,因此需要一次调整,调整从array.length-1处开始
-
- 首先找到array.length-1 父亲节点,如果有左右孩子,进行比较进行交换,依次循环往前进行处理
3. 依照按照1,2步骤循环进行,直到排序完成
Java 实现代码逻辑如下:
1 public class HeapSort { 2 3 public static void main(String[] args) { 4 int[] array = new int[]{5, 3, 6, 2, 1, 9, 4, 8, 7}; 5 6 HeapSort heapSort = new HeapSort(); 7 heapSort.heapSort(array); 8 9 for (int i = 0; i < array.length; i++) { 10 System.out.print(array[i]+" "); 11 } 12 } 13 14 15 public void heapSort(int[] array) { 16 17 for (int i = 0; i < array.length; i++) { 18 // 将array[array.length-1-i]创建为堆 19 createMaxHeap(array, array.length - 1 - i); 20 // 因为大顶堆,所以最大值始终处于array[0], 21 // 交换array[0]与array[array.length-1-i] 22 swap(array, 0, array.length - 1 - i); 23 } 24 } 25 26 // 调整成堆 27 private void createMaxHeap(int[] array, int lastIndex) { 28 // 从当前位置的父亲节点 29 for (int i = (lastIndex - 1) / 2; i >= 0; i--) { 30 // 记录当前的位置节点 31 int k = i; 32 // 条件成立,则说明有孩子节点,此时判断是否满足堆的特性 33 while (2 * k + 1 <= lastIndex) { 34 // 默认左孩子为最大 35 int biggerIndex = 2 * k + 1; 36 // 在判断一下看是否有右孩子 37 if (biggerIndex < lastIndex) { 38 // 如果存在右孩子,并且右孩子大,则将默认索引加1 39 if (array[biggerIndex] < array[biggerIndex + 1]) { 40 biggerIndex++; 41 } 42 } 43 44 // 此时在跟父亲节点作比较 45 if (array[k] < array[biggerIndex]) { 46 swap(array, k, biggerIndex); 47 } else { // 如果不小于则结束本次循环,下一个节点的比较 48 break; 49 } 50 } 51 } 52 } 53 54 // 交换两个元素 55 private void swap(int[] data, int i, int j) { 56 if (i == j) { 57 return; 58 } 59 data[i] = data[i] + data[j]; 60 data[j] = data[i] - data[j]; 61 data[i] = data[i] - data[j]; 62 }
博客描述不对之处,请指正,希望给大家带来帮助,谢谢。
以上是关于堆排序算法的实现的主要内容,如果未能解决你的问题,请参考以下文章