en造数据结构与算法C# 之 堆排序

堆的特点 

堆排序有两个分类:大顶堆,小顶堆

比如大顶堆就是说所有根节点的值都比左右子节点大

en造数据结构与算法C# 二叉排序树 泛型类的基本构成-CSDN博客

en造数据结构与算法C# 之 二叉排序树的增/查-CSDN博客

en造数据结构与算法C# 之 二叉排序树的删除-CSDN博客

 

堆排序的思路

堆构成

以大顶堆为例,对于索引从0开始的数组,其实现思路如下:

堆构成,首先是找到非叶子节点的子树

关键:完全二叉树的性质

非叶子节点的索引为(0,n/2-1),向下取整

叶子节点的索引从(n/2,n-1),向下取整

之后将根节点与两个子节点比较后,看是否交换,之后依次向上找子树,不断递归调整

        

对于一个数组,堆构成的方法为,其中n是数组长度

  static void Heapify(int[] array, int n, int i) {
  int largest = i; // 初始化最大值为根节点
  int left = 2 * i + 1; // 左子节点
  int right = 2 * i + 2; // 右子节点

  // 如果左子节点大于根节点
  if (left < n && array[left] > array[largest]) {
      largest = left;
  }

  // 如果右子节点大于最大值节点
  if (right < n && array[right] > array[largest]) {
      largest = right;
  }

  // 如果最大值不是根节点
  if (largest != i) {
      int swap = array[i];
      array[i] = array[largest];
      array[largest] = swap;

      // 递归地调整受影响的子树
      Heapify(array, n, largest);
  }

堆排序

这一步是在数组中利用上面的构成方法,进行堆的排序

首先,先执行一次构成堆的方法,将最大的值拿到树顶

其次,因为排序,所以需要将数值大的元素和最后一位交换

然后,将首位和末尾的数值进行交换,再进行一次堆构成的方法,并且忽略最后一位

以此类推

    static void HeapSorts(int[] array) {
        int n = array.Length;

        // 构建堆
        for (int i = n / 2 - 1; i >= 0; i--) {
            Heapify(array, n, i);
        }

        // 一个个取出元素
        for (int i = n - 1; i > 0; i--) {
            // 将当前堆顶(最大值)与堆的最后一个元素交换
            int temp = array[0];
            array[0] = array[i];
            array[i] = temp;

            // 调整堆
            Heapify(array, i, 0);
        }
    }

总览: 

using System;

class Program
{
    static void Main()
    {
        int[] array = { 50, 10, 200, 30, 70, 40, 100, 60, 20, 65, 5 };
        HeapSort(array);
        Console.WriteLine(string.Join(", ", array));
    }

    static void HeapSort(int[] array)
    {
        int n = array.Length;

        // 构建堆
        for (int i = n / 2 - 1; i >= 0; i--)
        {
            Heapify(array, n, i);
        }

        // 一个个取出元素
        for (int i = n - 1; i > 0; i--)
        {
            // 将当前堆顶(最大值)与堆的最后一个元素交换
            int temp = array[0];
            array[0] = array[i];
            array[i] = temp;

            // 调整堆
            Heapify(array, i, 0);
        }
    }

    static void Heapify(int[] array, int n, int i)
    {
        int largest = i; // 初始化最大值为根节点
        int left = 2 * i + 1; // 左子节点
        int right = 2 * i + 2; // 右子节点

        // 如果左子节点大于根节点
        if (left < n && array[left] > array[largest])
        {
            largest = left;
        }

        // 如果右子节点大于最大值节点
        if (right < n && array[right] > array[largest])
        {
            largest = right;
        }

        // 如果最大值不是根节点
        if (largest != i)
        {
            int swap = array[i];
            array[i] = array[largest];
            array[largest] = swap;

            // 递归地调整受影响的子树
            Heapify(array, n, largest);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值