堆排序

学到了堆排序,并将重要代码都注释了,有需要的可以白嫖,欢迎纠正。
堆排序的基本思想:
将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次大值。如此反复执行,便能得到一个有序序列了
步骤:
a.将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;

b.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;

c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。

#include<iostream>
using namespace std;
void swap(int &num1, int &num2)
{
	int temp = num1;
	num1 = num2;
	num2 = temp;
}

/***堆调整函数***/
/*已知arr[]中记录的关键字除arr[s]之外都满足大顶堆的定义*/
/*本函数一次只能调整arr[s],使得arr[]成为一个大顶堆*/
void HeapAdjust(int arr[], int s, int high)			// s 要被调整的下标,  high 参与排序的最后一个结点的下标
{
	int temp;
	temp = arr[s];		//先将要调整的关键字保存
	int j = 2 * s + 1;	//s的左孩子下标
	while (j <= high)
	{
		if (j < high&&arr[j] < arr[j + 1])		// 如果有两个孩子(j<high),且左孩子小于右孩子,
			j++;							//	就j+1,使j 就指向右孩子,最终目的找出孩子结点最大值的那个,
		
		if (temp < arr[j])		//将要调整的结点与其“每一代子孙结点的最大值(arr[j])”比较
		{
			arr[s] = arr[j];	//如果要调整的值比孩子的值小,
			s = j;			//更新s值,保存调整值要插入的位置下标——arr[s] = temp;

			j = 2 * s + 1;	//移向下一代,继续比较,找到适合插入调整值的位置
		}
		else			//要调整的值大于孩子结点,直接返回。
			break;
	}
	arr[s] = temp;		//插入
}


/****堆排序  首结点下标为0!!!***/
void HeapSort(int arr[], int n)
{
	for (int i = n / 2 - 1; i >= 0; i--)	// n/2-1为最后一个非叶结点,循环到0,调整所有的非叶结点
	{
		HeapAdjust(arr, i, n - 1);	//第一个下标为0,所以最后一个下标为n-1
	}

	for (int i = n - 1; i > 0; i--)//for循环是与堆顶数据交换,所以去掉堆顶下标i=0
	{
		swap(arr[i], arr[0]);		//将堆顶记录与当前未经排序子序列的最后一个数据交换
		
		HeapAdjust(arr, 0, i - 1);	//交换完后,对新的堆顶记录进行调整,调整范围要除去新产生的排序序列,如第一次除去arr[n-1](找出的最大值)

	}
}

int main()
{
	int arr[8] = { 1,6,7,9,3,4,0,8 };
	HeapSort(arr, 8);

	for (int i = 0; i < 8; i++)
	{
		cout << arr[i] << "  ";
	}

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值