堆排序--HeapSort()

一.堆排序

1.首先区别于升序打印或者降序打印

(1)升序打印:

void TestHeapSort()
{
	// 升序打印 -- 小堆
	// 降序打印 -- 大堆
	HP hp;
	HeapInit(&hp);
	int a[] = { 27, 15, 19, 18, 28, 34, 65, 49, 25, 37 };
	for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
	{
	HeapPush(&hp, a[i]);
	}

	while (!HeapEmpty(&hp))
	{
	printf("%d ", HeapTop(&hp));
	HeapPop(&hp);
	}
	printf("\n");

	int a[] = { 27, 15, 19, 18, 28, 34, 65, 49, 25, 37 };
	HeapSort(a, sizeof(a) / sizeof(int));
}

(2)排序

         升序排序--建大堆(父节点值大于子节点)

         降序排序--建小堆(父节点值小于子节点)

         

2.堆排序初级版本(不建议使用版本):

//不好/错误方式:
  HP hp;//定义个堆类型的结构体
  HeapInit(&hp);
  for(int i=0;i<n;i++)
  {
    HeapPush(&hp,a[i]);
  }
  int i=0;
  while(!HeapEmpty(&hp))
  {
    a[i]=HeapTop(&hp);
    HeapPop(&hp);
  }

存在问题:

                  1.内存泄露(小问题)-->添加HeapDestroy

                  2.要先写一个Hp数据结构,复杂

                  3.有O(N)空间复杂度

3.优化版本(正确版本):

整体思路:

#堆排序

 一、建堆(由数组建堆)(堆排序的前提是有堆)

思路:方式1.直接将 已给的数组的每个元素都 进行向上排序    (没有条件限制)

          方式2.向下排序          (parent的左右两边都必须是堆)

二、堆排序

思路:## 升序--大堆--将堆顶最大的元素和最后一个元素交换,放在最后一位,然后size--,每完成一次,堆剩下的数进行一次向下调整,和HeapPop的思路类似。依次将最后一位放最大,倒数第二位放次大,.......依次类推,可以堆进行排序。

(升序--而不是建小堆,因为选出最小放在首位的容易,但选出次小的放在第二位难,之后的都不容易放。只能选一个次小的,再建堆,选次小,建堆,时间复杂度会达到O(N^2),该方法不是不可以,而是效率太差,没有使用到堆的优势  )

//简洁版本
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

voidAdjustUp(HPDataType*a,intchild)
{
    intparent=(child-1)/2;
    //while (parent >= 0)
  while(child>0)
  {
    //if (a[child] < a[parent])
    if(a[child]>a[parent])
    {
    Swap(&a[child],&a[parent]);
    child=parent;
    parent=(child-1)/2;
    }
    else
    {
    break;
    }
 }
}


void AdjustDwon(int* a, int size, int parent)
{
	int child = parent * 2 + 1;
	while (child < size)
	{
		
		if (child + 1 < size && a[child + 1] > a[child])
		{
			++child;
		}

		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

// 降序 -- 建小堆
// 升序 -- 建大堆
void HeapSort(int* a, int n)
{

    // 建堆方式1:O(N*logN)
    for (int i = 1; i < n; ++i)
    {
	    AdjustUp(a, i);//向上排序
    }

	// 建堆方式2:O(N)
	for (int i = (n - 1 - 1) / 2; i >= 0; --i)
	{
		AdjustDwon(a, n, i);//向下排序
	}

	// O(N*logN)
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDwon(a, end, 0);
		--end;
	}
}

 

ps: 以上: int i=(n-1-1)/2解析: n-1是最后一个节点的下标,((n-1)-1)是其父亲的节点,也就是最后一个非叶子节点的下标。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值