您的位置:首页 > 其它

改进的堆排序算法

2013-11-04 14:49 232 查看
对堆排序的改进

1.将数据初始化为大顶堆,交换第一个和最后一个元素,这里是不变的

2.重新构造大顶堆是,首先让第一个元素下降h/2的高度(h 为堆的高度)

3.下降了h/2层后判断这个元素与它的父节点谁大,如果父节点大继续下沉,下沉的结束条件为h=0

   如果父节点小,表明第一个元素下沉时走过头了,然后要往回走,进行上浮操作,上浮操作是肯定能够找到第一个元素的最终位置的

4.循环n-1次程序运行完成。

实现代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
#include <math.h>

/*******************************************************
*首次初始化时构建大顶推
********************************************************/
void buildheap(int a[], int n)
{
for(int i=n/2; i>=1; i--)
{
int temp = a[i];
int j = 2*i;
while(j <= n)
{
if(j<n && a[j]<a[j+1])
{
++j;
}

if(temp >= a[j])
{
break;
}

a[j/2] = a[j];
j = 2*j;
}
a[j/2] = temp;
}
int t = a
;
a
= a[1];
a[1] = t;
}

/************************************************************
*第一个元素下沉h/2层,并返回a[1]在h/2的数组下标
*************************************************************/
int getdown(int a[], int start, int deep, int n)
{//头结点下沉到第d层
int i = start;
int j = 2*i;
int d = 0;
int temp = a[start];
while(j<=n && d<=deep)
{
d++;
if(j<n && a[j]<a[j+1])
{
++j;
}
a[i] = a[j];
i = j;
j = 2*i;
}
a[i] = temp;
return i;
}

/*************************************************************
*函数功能:a[1]下沉走过头了,再往回走
*************************************************************/
void up(int a[], int start)
{
int temp = a[start];
int i = start;
while(a[i] > a[i/2])
{
a[i]=a[i/2];
i = i/2;
}
a[i] = temp;
}

/****************************************************************
*改进后的堆排序
*定义一个长度d,在顶点下沉的过程中先先下沉d,然后和父节点比较再决定
*结点是继续下沉还是上升,从而来减少比较次数
******************************************************************/
void main()
{
int n; //数组的长度

printf("请输入数组的长度:\n");
scanf("%d",&n);

//初始化数组
int *a = (int *)malloc((n+1)*sizeof(int));
srand(time(0));
for(int i=0; i<n+1; i++)
{
a[i] = rand()%100;
}

//输出排序前的数组
printf("\n");
printf("排序之前的数组:\n");
for(i=1; i<n+1; i++)
{
printf("%d\t",a[i]);
}

//排序
buildheap(a,n);

//改进部分
int h;    //堆高度减一
int count=n-1;
while(count > 1)
{
h = (int)(log(count+1)/log(2));
int start=1;
while(true)
{
//先下降deep层
int i = getdown(a,start,h/2,count);
//判断上浮还是继续下沉
if(a[i] >= a[i/2])
{//上浮
up(a,i);
int temp = a[count];
a[count] = a[1];
a[1] = temp;
break;
}
else
{//继续下沉
start = i;
h = h/2;
if(h <= 0 || 2*start>count)
{
int temp = a[count];
a[count] = a[1];
a[1] = temp;
break;
}
}
}
count--;
}

//输出排序后的数组
printf("\n");
printf("排序后的数组:\n");
for(i=1; i<n+1; i++)
{
printf("%d\t",a[i]);
}

free(a);

}


 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息