八大排序———堆排序

堆排序算法原理:

  1.堆排序说明:堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定的索引元素。堆分为大根堆和小根堆,是完全二叉树。大根堆要求每个节点的值都不大于其父节点的值。在数组的非降序排序中,使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定是在堆顶。

  2.算法描述:(建堆 -》调整堆 -》堆排序)

    ①将初始待排序关键字序列(R1 R2 R3 R4.......Rn)构建成大顶堆,次堆为初始的无序区(只满足大顶堆的要求)

    ②将堆顶元素R[1]和最后一个元素R[N]进行交换,此时得到新的无序区(R1R2R3..Rn)和新的有序区R[N],且满足有序区域的数据都是大于无序区中的

    ③由于交换后新的堆顶R[1]可能违反大根堆的性质,因此需要将无序区(R1 R2....Rn-1)调整为新堆,然后再次将R[1]和无序区最后一个元素交换,得到新的无序区(R1 R2 R3.. Rn-2)和新的有序区。不断重复此过程,直至整个排序完成。

动图演示

代码解析:

/*.............................
filename : heapsort.c
create time :2018-10-7
E-mail :1564676944@qq.com
.............................*/
#include<assert.h>
#include<iostream>
using namespace std;
void swap(int* a,int* b)
{
		int temp = *a;
		*a = *b;
		*b = temp;
}
void FilerDown(int* arr,int start,int end)
{
		assert(arr != NULL);
		int i = start;
		int j = 2*i +1;

		int tmp = arr[i];
		while(j<=end)
		{
				if(j+1<=end && arr[j+1]>arr[j])
				{
						j += 1;
				}
				if(tmp < arr[j])
				{
						arr[i] = arr[j];
						i = j;
						j = j*2+1;
				}
				else
						break;
		}
		arr[i] = tmp;

}
void make_heap(int* arr,int len)
{
		assert(arr != NULL);
		int end = len - 1;

		int pos = (end -1)/2;
		while(pos >= 0)
		{
				FilerDown(arr,pos,end);
				--pos;
		}

}
void heap_sort(int* arr,int len)
{
		assert(arr != NULL);
		int end = len -1;
		make_heap(arr,len);

		for(int i = end;i>0;--i)
		{
				swap(&arr[0],&arr[i]);
				FilerDown(arr,0,i-1);
		}
}
void print(int* arr,int len)
{
		for(int i = 0;i < len;++i)
		{
				cout<<arr[i]<<" ";
		}
		cout<<endl;
}
int main()
{
		int arr[] = {12,56,34,59,78,9,99,15,46,32,56};
		int len = sizeof(arr)/sizeof(arr[0]);

		heap_sort(arr,len);

		print(arr,len);
		return 0;

}

效率分析:

  堆排序和直接选择排序相反:在任何时间堆排序中无序区域总是在有序区域之前,且有序区域是在原向量的尾部有后往前逐步扩大至整个向量。

堆排序的时间,主要是在建立初始堆,和反复重建堆这两部分的时间开销构成,平均时间复杂度O(N*logN)(最坏最优都是)。

  由于建立初始堆所需要的比较次数较多,所以堆排序不适宜于记录数较小的文件。空间复杂度为O(1)

算法稳定性: 

  它是不稳定的排序方法。会发生跳跃性的交换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值