常见排序算法:堆排序算法

基本思想:先将待排序数据化为完全二叉树,从length/2+1处开始寻找他的左/右子节点,将较大值与父节点进行交换,最后遍历到根节点处,此时根节点为所有数中的最大值,将该值与最后一个元素进行交换,length=length-1,又从父节点开始进行比较,继续寻找较大值。将找到的较大值与length-2处进行交换。依次类推。

 1.首先将待排序的数组元素转换为完全二叉树,根节点对于数组第一个元素,按先序遍历进行排序,即根节点,左子节点,右子节点。

2.待排序数组长度为length=8,首先进行堆的初始化,定义一个for循环for(i=length/2-1;i>0;i--)。i首先等于8/2-1=3;因此从a[3]处作为父节点,寻找比它大的左右子节点。此时6作为父节点,3作为左子节点,6没有右子节点,6是最大值因此不需要进行交换。进入下一轮for循环

3.i此时等于2。因此a[2]处作为父节点,它的左子节点右子节点分别为6和1,6比4大,此时最大值位置max=2*2+1处,1比4小,max位置仍为2*2+1处,因此交换a[2]与a[2*2+1]处的元素。交换完成后a[5]作为父节点继续寻找它的左右子节点,此时a[5]已经为叶子节点,没有子节点,因此该轮循环结束。

4.i此时等于1。因此a[1]处作为父节点,它的左子节点右子节点分别为6和7,5<6,max位置为3处。5<7,max位置变为4。因此交换a[1]与a[max]处的元素。交换后5变为右子节点,此时5已经是叶子节点因此不需要进行继续寻找子节点,该轮循环结束。

5.i此时等于0。因此a[0]处作为父节点,它的左子节点右子节点分别为7和6,7<12,6<12,max位置为0。此轮循环结束,i变为-1循环结束。此时父节点为数组中的最大值。

6.进入另外一个循环for(i = len - 1; i >=0; i--),该循环将栈顶元素与最后一个元素进行交换。i=7,将a[0]与a[7]进行交换。

7.此时又从栈顶开始,a[0]作为父节点,比较左右子节点。7>3,max=1。交换a[1]和a[0]。

7.交换的元素a[1]不是叶子节点,需要继续迭代进行交换。保证交换的元素比它子节点大。因此将a[1]与a[3]进行交换。12作为最大元素不在参与上面的交换。此时7作为最大值位于父节点处。

8.将该循环将栈顶元素与最后一个元素进行交换。此时最后一个元素为a[length-2]。即7与1进行交换。

9.交换后i=length-1;又从a[0]开始继续迭代比较。将1和左子节点的6进行交换。交换后继续将1作为父节点和它的右子节点5进行交换。

10.当i<0时,排序完成。

代码:


//list:待调整的数组 index:待调整的节点下标 len:数组长度
void HeapAdjust(int list[], int index, int len)
{
	int max = index;//保存父节点下标
	int lchild = index * 2 + 1;//下标从0开始
	int rchild = index * 2 + 2;//下标从0开始

	//左子节点大于父节点
	if (lchild<len&&list[lchild]>list[max])
	{
		max = lchild;
	}
	//右子节点大于父节点
	if (rchild<len&&list[rchild]>list[max])
	{
		max = rchild;
	}
	if (max!=index)
	{
		swap(list[max], list[index]);
		HeapAdjust(list, max, len);
	}

}
//初始化堆,大顶堆,从小到大
void HeapSort(int list[], int len)
{
	//初始化堆
	for (int i = len / 2 - 1; i >= 0; i--)
	{
		HeapAdjust(list, i, len);
	}
	//交换堆顶元素和最后一个元素
	for (int i = len - 1; i >=0; i--)
	{
		swap(list[0],list[i]);
		HeapAdjust(list, 0, i);
	}
}
int main()
{
	int list[] = { 12, 5, 4, 6, 7, 6, 1 ,3};

	HeapSort(list, sizeof(list) / sizeof(int));

	for (int i = 0; i < sizeof(list) / sizeof(int); i++)
	{
		cout << list[i] << endl;
	}
}

堆排序是一种不稳定的排序方法,最好、最坏、平均时间复杂度:O(n\log n),空间复杂度为O(1)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章