堆排序算法的实现

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<stdio.h>
#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] 之间没有大小约束关系

对于堆的基本定义我们已经很清晰了,下面我们将详细的介绍一下堆排序的思路

堆排序的整体思路如下(以大顶堆为例说明,小顶堆同理哈)

  1. 根据大定堆的概念array[0]始终是最大的,因此与array[array.length-1]进行交换,此时就形成了 array[0].... array[array.length-2] 的无序数组和 array[array.length-1] 的有序数组
  2. 在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     }

 

 博客描述不对之处,请指正,希望给大家带来帮助,谢谢。

以上是关于堆排序算法的实现的主要内容,如果未能解决你的问题,请参考以下文章

排序算法总结之堆排序

排序算法堆排序的Python实现及算法详解

算法2 排序算法:直接选择排序和堆排序

堆排序算法以及python实现

选择排序(简单选择排序堆排序的算法思想及代码实现)

Heapsort 堆排序算法详解(Java实现)