C# 排序算法之堆排序

堆排序(Heap Sort)是一种基于比较的排序算法,它利用堆这种数据结构所设计。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子节点的键值或索引总是小于(或者大于)它的父节点。

在堆排序算法中,我们首先将待排序的序列构造成一个大顶堆(或小顶堆),此时,整个序列的最大值(或最小值)就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值(或最小值)。然后将剩余n-1个序列重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。

以下是堆排序算法的C#实现:

using System;

class Program
{
    static void Main(string[] args)
    {
        int[] arr = { 12, 11, 13, 5, 6, 7 };
        HeapSort(arr);
        Console.WriteLine("Sorted array: ");
        PrintArray(arr);
    }

    // 堆排序方法
    static void HeapSort(int[] arr)
    {
        int n = arr.Length;

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

        // 一个个从堆顶取出元素
        for (int i = n - 1; i > 0; i--)
        {
            // 移动当前根到末尾
            Swap(ref arr[0], ref arr[i]);

            // 调用max heapify在减少的堆上
            Heapify(arr, i, 0);
        }
    }

    // 维持堆的性质
    static void Heapify(int[] arr, int n, int i)
    {
        int largest = i; // 初始化最大为根
        int left = 2 * i + 1; // 左 = 2*i + 1
        int right = 2 * i + 2; // 右 = 2*i + 2

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

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

        // 如果最大不是根
        if (largest != i)
        {
            Swap(ref arr[i], ref arr[largest]);

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

    // 交换两个元素
    static void Swap(ref int x, ref int y)
    {
        int temp = x;
        x = y;
        y = temp;
    }

    // 打印数组的方法
    static void PrintArray(int[] arr)
    {
        foreach (int i in arr)
        {
            Console.Write(i + " ");
        }
        Console.WriteLine();
    }
}

在这个实现中,HeapSort 方法是堆排序的入口点。它首先通过从最后一个非叶子节点开始向前遍历,对每个节点调用 Heapify 方法来构建大顶堆。然后,它通过将堆顶元素(即当前最大值)与数组的最后一个元素交换,并减小堆的大小(不考虑已经排序的最后一部分),再对新的堆顶元素调用 Heapify 方法来保持堆的性质,从而逐步将数组排序。

Heapify 方法是维持堆性质的关键。它接受一个数组、堆的大小和当前节点的索引作为参数。它首先假设当前节点是子树中的最大值,然后与其子节点进行比较。如果发现有子节点大于当前节点,则更新最大值的索引,并在需要时递归地调用 Heapify 方法以保持子树的堆性质。

Swap 方法用于交换两个整数变量的值。

PrintArray 方法用于打印排序后的数组。

堆排序的时间复杂度为O(n log n),是一种不稳定的排序算法,但它不需要额外的存储空间(除了几个临时变量用于交换),并且在实际应用中表现出良好的性能。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AitTech

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

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

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

打赏作者

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

抵扣说明:

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

余额充值