八大排序学习之七堆排序

来源:互联网 发布:淘宝外卖超出配送范围 编辑:程序博客网 时间:2024/05/21 15:01

我们学习堆排序之前需要弄清堆的概念,计算机常说的堆有两种一种是操作系统上的堆内存,还有一种是数据结构上的堆,今天我们来讲数据结构上的堆,数据结构上的堆也有几种,二叉堆,二项堆,斐波那契堆,通常我们把二叉堆成为简称为堆。

堆排序也是一种效率很高的排序,平均时间复杂度为:O(nlogn)

二叉堆是一种完全二叉树,其中非叶结点与父节点的关系总满足,i<=2*1+1&&i<=2*(i+1)或者i>=2*1+1&&i>=2*(i+1)的关系,i为父节点

其中,i<=2*1+1&&i<=2*(i+1)称为小顶堆,i>=2*1+1&&i>=2*(i+1)称为大顶堆。

堆排序的思想如下:

首先将指定的一组数转化成大顶堆或者小顶堆,通过父节点与子节点的比较进行前后替换,通过递归遍历所有节点,每次从顶部取出未排序的最大值跟未排序的最后一个交换, 例如:堆A[0,n-1],先交换a[0]和A[n-1],调整堆,交换A[0]和A[n-2],调整堆......,交换A[0]和a[1],交换完毕。

得出排序结果。

(初始化堆,循环(交换顶部和未排序的最后一个,调整堆)。

举个例子:

第一步、给个数组a[4]={3,1,2,4}

转换得一二叉树

   3

1    2

4

第二步、堆化,从第一个非叶结点开始调整,左子节点,1和4交换得

   3

4    2

1

第三步继续堆化,3跟4交换得初始大顶堆

   4

3    2

1

下面为关键步骤:

第四步,将最顶的与最后的交换,把最大的放到最后面的节点。

  1 

3  2

4

交换了之后,明显1和3不符合堆的概念,因为需要继续调整

  3

1  2

最顶的和未排序的最后一个交换,3和2交换得

  2

1  3

4

2和1交换得

  1

2   3

节点访问完毕,得结果。

 关键代码:

void max_heapify(int*arr,int index,int len){  int l=2*index+1;  int r=2*(index+1);  int largest;  if(l<len&&arr[l]>arr[index])    largest=l;  else    largest=index;  if(r<len&&arr[r]>arr[largest])    largest=r;  if(largest!=index)  {    //将最大元素提升,并递归    myswap(&arr[largest],&arr[index]);    max_heapify(arr,largest,len);  }}
下面给出完整代码:

// List.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include<stdlib.h>#include <time.h> #define NUMLEN 20000 inline void myswap(int*a,int*b){  *a=*a^*b;    *b=*a^*b;    *a=*a^*b;  }void max_heapify(int*arr,int index,int len){  int l=2*index+1;  int r=2*(index+1);  int largest;  if(l<len&&arr[l]>arr[index])    largest=l;  else    largest=index;  if(r<len&&arr[r]>arr[largest])    largest=r;  if(largest!=index)  {    //将最大元素提升,并递归    myswap(&arr[largest],&arr[index]);    max_heapify(arr,largest,len);  }}void build_maxheap(int*arr,int len){//建立大顶堆  int i;  if(arr==NULL||len<=1)    return;  for(i=len/2+1;i>=0;--i)    max_heapify(arr,i,len);}void heap_sort(int*arr,int len){  int i;  if(arr==NULL||len<=1)    return;  build_maxheap(arr,len);   for(i=len-1;i>=1;--i){    myswap(&arr[0],&arr[i]);    max_heapify(arr,0,--len);  }}int main(int argc, char* argv[]){int a[NUMLEN];srand((int)time(NULL));for(int i=0;i<NUMLEN;i++)a[i]=rand()%NUMLEN;float nstart=clock();heap_sort(a,NUMLEN);for(i=0;i<NUMLEN;i++)printf("%d\n",a[i]);float nend=clock();printf("共用时%.3fs\n",(nend-nstart)/1000);return 0;}
20000个数据的时间情况:




0 0
原创粉丝点击