排序-堆排序

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

算法描述
    
①建堆,建堆是不断调整堆的过程,从len/2处开始调整,一直到第一个节点,此处len是堆中元素的个数。建堆的过程是线性的过程,从len/2到0处一直调用调整堆的过程,相当于o(h1)+o(h2)…+o(hlen/2) 其中h表示节点的深度,len/2表示节点的个数,这是一个求和的过程,结果是线性的O(n)。
②调整堆:调整堆在构建堆的过程中会用到,而且在堆排序过程中也会用到。利用的思想是比较节点i和它的孩子节点left(i),right(i),选出三者最大(或者最小)者,如果最大(小)值不是节点i而是它的一个孩子节点,那边交互节点i和该节点,然后再调用调整堆过程,这是一个递归的过程。调整堆的过程时间复杂度与堆的深度有关系,是lgn的操作,因为是沿着深度方向进行调整的。
③堆排序:堆排序是利用上面的两个过程来进行的。首先是根据元素构建堆。然后将堆的根节点取出(一般是与最后一个节点进行交换),将前面len-1个节点继续进行堆调整的过程,然后再将根节点取出,这样一直到所有节点都取出。

算法的时间复杂度
    堆排序过程的时间复杂度是O(nlgn)。因为建堆的时间复杂度是O(n)(调用一次);调整堆的时间复杂度是lgn,调用了n-1次,所以堆排序的时间复杂度是O(nlgn)

代码实现

#include <iostream>
using namespace std;

inline void swap(int *a, int *b)
{
	int temp = *a; *a = *b; *b = temp;
}

void adjustHeap(int arr[], int len, int index)
{
	int temp = arr[index];
	for(int k  = index * 2 + 1; k < len; k = k*2 + 1)
	{
		// 如果右边值大于左边值,指向右边
		if(k + 1 < len && arr[k] < arr[k+1])
		   k++;
		// 如果子节点大于父节点,将子节点值赋给父节点,并以新的子节点
		// 作为父节点(不用交换)
		if(arr[k] > temp)
		{
			arr[index] = arr[k];
			index = k;
		
		}else
			break;	
	
	}
	arr[index] = temp;

}

void heapSort(int arr[], int len)
{
	//1、构建大根堆
	for(int i = len / 2 - 1; i >= 0; i--)
		adjustHeap(arr, len, i);	
	//2、调整堆结构和交换堆顶元素和最后一个元素
	for(int j = len - 1; j > 0; j--)
	{
		swap(&arr[0], &arr[j]);
		adjustHeap(arr, j, 0);
	
	}	

}


int main()
{
	int arr[] = { 9,8,7,12,15,23,1,0,6,2};
	int len = sizeof(arr) / sizeof(int);
	heapSort(arr, len);

	for(int i = 0; i != len; i++)
		cout << arr[i] << " ";
	cout << endl; 	
	return 0;
}

运行结果

0 1 2 6 7 8 9 12 15 23


猜你喜欢

转载自blog.csdn.net/snailcpp/article/details/79996839