堆排序

堆排序

堆是一种数据结构,一种叫做完全二叉树的数据结构。

堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。

大顶堆:a[i] >=a[2i+1] && ar[i] >= a[2i+2]

小顶堆:a[i] <= a[2i+1] && a[i] <= a[2i+2]

堆排序的基本思想:

堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了

算法思想:

1.把一组数据a[n]调整成大根堆或小根堆,用heapSize来实时记录数组尚未排序的数据的数量,初始值为a[n]长度n

2.将a[0]与a[–heapSize]交换值,因为一开始就把数据调整为大根堆,该步骤相当于把已经找出数组中最大的数据,并放到了最后一位,不再处理。

3.a[0]与a[–heapSize]交换值后,也破坏了大根堆,但除了a[0]以外,数组其他数据还是保持大根堆状态。此时就是一直将a[0]数据“下沉”,让他不断和孩子节点比较,直到找到孩子节点都比它小,停止“下沉”,被破坏了的大根堆又重新被调整为大根堆。不断–heapSize,不断调整大根堆,每次都把a[0]与a[–heapSize]交换值,最终数组有序。

#include<bits/stdc++.h>
using namespace std; 

void swap(int *a,int n,int m)
{
	int t;
	t=a[n];
	a[n]=a[m];
	a[m]=t;
 } 
 void heapify(int *a,int index,int heapsize)
 {
 	int left=index*2+1;
 	while(left<heapsize)//判断左孩子是否越界,若越界说明左孩子已经到达最下面 
 	{
 		//比较两个孩子谁的值大 ,谁的值大谁就是largest 
 		int largest=left+1<heapsize&&a[left+1]>a[left]?left+1:left;
 		//比较父节点和孩子节点的大小
 		largest=a[largest]>a[index]?largest:index; 
 		if(largest==index)//若发现孩子节点都比a[index]小,则循环结束
 		break;
 		swap(a,largest,index);
 		index=largest;
 		left=index*2+1;
	 }
 }
void heapInsert(int *a,int index)//把数组调成大根堆 
{
	while(a[index]>a[(index-1)/2])
	{
		swap(a,index,(index-1)/2);
		index=(index-1)/2;
	}
}

void heapSort(int *a,int n)
{
	if(a==NULL||n<2)
	return ;
	for(int i=0;i<n;i++)
	heapInsert(a,i);
	int heapSize=n;
	swap(a,0,--heapSize);//交换后大根堆的最大的值到数组最后一个位置 
	while(heapSize>0)
	{
		//每次都把数组中0-heapSize调整成大根堆 
		heapify(a,0,heapSize);
		swap(a,0,--heapSize);
	 } 
	
}
 int main()
 {
 	int n;
 	cin>>n;
 	int a[n];
 	for(int i=0;i<n;i++)
 	{
 		cin>>a[i];
	 }
	 heapSort(a,n);
	  for(int i=0;i<n;i++)
	  cout<<a[i]<<" ";
	  cout<<endl;
 	return 0;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值