堆排序(升序&降序)

        堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏、最好、平均时间复杂度均为O(nlogn),是不稳定排序

小根堆(最小堆):每个结点的值都<=其左右孩子结点的值。

大根堆:每个结点的值都>=其左右孩子结点的值。

 

没有规定其左右孩子之间的大小关系,这与二叉排序树不同。

结点的编号:自顶向下,自左至右连续给结点编号0,1,2,…,n-1,之后按结点编号将树中各结点顺序的存放于顺序表中。

i = 0位置为根结点,没有双亲;i>0时,双亲结点为(i-1)/2;

若2*i+1<n,则i的左孩子为2*i+1;若2*i+2<n,则i的右孩子为2*i+2;

左孩子i都为奇数,右孩子i都为偶数;

i所在的层次为log2(i+1);

 堆排序的降序排序

1.将待排序的序列构建成一个最小堆(先局部再整体从底向上)

        整个序列的最小值为根节点的值

 

2.将根节点的值与末尾元素的值交换

3.剩余n-1个元素继续进行上述两步,直到只剩一个元素,排序完成

创建小根堆

        使用tmp存根的值,i存根下标,j存其左子下标,先对比其左右两子的大小(如果存在),使j指向小的。

        对比根和小的子孩子的值,如果根小则排列完成,否则交换根的小子的值,之后继续排后面的。

        将tmp赋给nums[i],它应该在的地方

void FilterDown(int *nums,int start,int end)//start是当前根结点下标,end为当前小根堆结束下标
{
	int i = start, j = i*2+1;
	int tmp = nums[start];//保存根结点的值
	while ( j<=end )
	{
		if(j+1<=end)//有左右两个孩子
			j = nums[j] < nums[j+1] ? j : j+1;//j指向小的孩子
		if (tmp < nums[j])
			break;
		else
			nums[i] = nums[j];//小的存到上面
		i = j;
		j = i * 2 + 1;
	}
	nums[i] = tmp;
}

堆排序

        先将序列排序成最小堆,然后一个一个交换,存在数组末尾,直到所有数排完。

void HeapSort(int *nums,int n)
{
	if (nums == nullptr || n < 2)return;
	int pos = (n-2)/2;//当前小根堆的根结点下标
//调整成最小堆
	while(pos>=0)
	{
		FilterDown(nums, pos, n-1);
		pos--;//下一个根
	}
//排序
	int end = n-1;
	while (end > 0)
	{
		swap(nums[0], nums[end]);//交换根与最后一个位置的值
		end--;//规模缩小
		FilterDown(nums, 0, end);
	}
}

堆排序的升序排序

        升序排序是创建大根堆来排,其他根上面的代码一样。

        创建堆也可以不用i,j两个存下标,下面用一个写大根堆(这是好久之前用C语言写的,有点不一样)

//创建大根堆
void CreateHeap(int* num, int index, int n)//index是下标,该下标的节点作为父节点
{
    int t = num[index];//存一下父节点的值
    int i = index * 2;//i指向其左子孩子下标(如果存在的话)
    while (i <= n)//有孩子
    {
        if (i < n)//有两个孩子
        {
            if (num[i] < num[i + 1])//找大的孩子
                i++;
        }
        if (t >= num[i])//如果根节点最大,就创建好了当前大根堆,出循环
            break;
        else//如果不是,则把最大的孩子放父节点
        {
            num[i / 2] = num[i];
            i *= 2;//i指向这个最大值孩子节点的左孩子
        }
    }
    num[i / 2] = t;//把刚开始的父节点值存在排好的大根堆的父节点
}
void HeapSort(int* num, int n)
{
    int i;
    for (i = n / 2; i >= 1; i--)//创建大根堆
        CreateHeap(num, i, n);
    for (i = n; i >= 1; i--)//大根堆的顶(最大的值)与大根堆最后一个值交换(排序放在数组的最后一个)
    {
        int t = num[1];
        num[1] = num[i];
        num[i] = t;
        CreateHeap(num, 1, i - 1);//排好一个所以i-1,顶上的根改变了,所以从1开始再一次排好大根堆
    }
}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曦樂~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值