堆排序

时间复杂度:O(n*logn)  以2为底的对数

空间复杂度:O(1)

稳定性:不稳定


        /// <summary>
        /// 堆排序
        /// </summary>
        /// <param name="nums">待排数据</param>
        public void Sort(int[] nums)
        {
            //基本思路:第1轮 将全部元素调整为大根堆,将根节点和最后一个元素交换
            //             第2轮 将除了最后一个元素外的元素调整为大根堆, 将根节点和倒数第二个元素交换
            //           。。。。。
            //将所有元素调整为大根堆  由于Heapify的使用限制  所以从最后一个非叶子节点开始调整
            //n个节点完全二叉树   下标0-n/2-1为非叶子节点
            for (int i = nums.Length / 2 - 1; i >= 0; i--)
            {
                Heapify(nums, i, nums.Length);
            }
            //需要调换n-1次
            for (int i = 0; i < nums.Length - 1; i++)
            {
                //将根和倒数第x个元素调换
                int tmp = nums[0];
                nums[0] = nums[nums.Length - i - 1];
                nums[nums.Length - i - 1] = tmp;
                //将前面的继续调整为大根堆  后面已经有序的除外
                Heapify(nums, 0, nums.Length - i - 1);
            }
        }


        /// <summary>
        /// 调整大根堆
        /// 使用前提:rootIndex的子节点的子树为空或者为大根堆   
        /// 该方法调整rootIndex根   可能会将子节点中大的和根交换  如果其子节点的子树为空则仍符合大根堆 
        /// 如果子节点的子树为大根堆  则调整后和根节点互换的子节点的子树不符合大根堆  方法会继续循环调整   另一个子节点仍符合大根堆
        /// 但是如果其子节点的子树不是大根堆  该方法只能调整和根节点互换的子节点的子树  另一个无法保证
        /// </summary>
        /// <param name="nums">待排序列</param>
        /// <param name="rootIndex">要调整的根节点下标</param>
        /// <param name="length">大根堆中的节点个数</param>
        void Heapify(int[] nums, int rootIndex, int length)
        {
            //下标从0开始   则rootIndex的左孩子  2*rootIndex+1
            int lchild;
            //判断孩子是否存在  并判断和谁交换(较大的交换)
            while ((lchild = 2 * rootIndex + 1) < length)
            {
                //左右孩子比较  确定较大的孩子
                if (lchild + 1 < length && nums[lchild] < nums[lchild + 1])
                {
                    lchild++;//lchild为要和根交换的
                }
                if (nums[rootIndex] < nums[lchild])
                {
                    //交换
                    int tmp = nums[lchild];
                    nums[lchild] = nums[rootIndex];
                    nums[rootIndex] = tmp;
                    //将lchild看做根  继续判断   因为以该节点为根的树可能不符合条件  
                    rootIndex = lchild;
                }
                else
                {
                    //如果符合大根  则退出
                    break;
                }
            }
        }



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值