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

堆的特点

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

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

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

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

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

堆排序的思路

堆构成

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

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

关键:完全二叉树的性质

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

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

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

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

cs 复制代码
  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);
  }

堆排序

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

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

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

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

以此类推

cs 复制代码
    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);
        }
    }

总览:

cs 复制代码
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);
        }
    }
}
相关推荐
爱吃生蚝的于勒2 小时前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法
冷眼Σ(-᷅_-᷄๑)5 小时前
Path.Combine容易被忽略的细节
c#·.net
ChoSeitaku7 小时前
链表循环及差集相关算法题|判断循环双链表是否对称|两循环单链表合并成循环链表|使双向循环链表有序|单循环链表改双向循环链表|两链表的差集(C)
c语言·算法·链表
Fuxiao___7 小时前
不使用递归的决策树生成算法
算法
我爱工作&工作love我7 小时前
1435:【例题3】曲线 一本通 代替三分
c++·算法
白-胖-子8 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-统计数字
开发语言·c++·算法·蓝桥杯·等考·13级
workflower8 小时前
数据结构练习题和答案
数据结构·算法·链表·线性回归
好睡凯8 小时前
c++写一个死锁并且自己解锁
开发语言·c++·算法
Sunyanhui18 小时前
力扣 二叉树的直径-543
算法·leetcode·职场和发展
一个不喜欢and不会代码的码农8 小时前
力扣105:从先序和中序序列构造二叉树
数据结构·算法·leetcode