C++堆排序的实现

简介: C++堆排序的实现

堆排序(Heap Sort)是一种原地、不稳定的排序算法,它利用堆这种数据结构来进行排序。堆是一种特殊的树形数据结构,满足堆的性质:对于每个节点 i,父节点的值始终大于或等于子节点的值(最大堆),或者父节点的值始终小于或等于子节点的值(最小堆)。

 

堆排序的基本原理如下:

1. **构建堆**:将待排序的元素构建成一个堆(通常是最大堆),即满足堆的性质。

2. **堆调整**:将堆顶元素(最大元素或最小元素)与堆的最后一个元素交换,然后对剩余的元素重新调整为堆,使其满足堆的性质。

3. **重复步骤2**:重复上述过程,每次将堆顶元素与当前堆的最后一个元素交换,并调整堆,直到所有元素都被取出,最终得到有序序列。

 

堆排序的特点:

- 时间复杂度为 O(nlogn),其中 n 是元素个数。

- 堆排序是原地排序,不需要额外的空间。

- 堆排序是不稳定的排序算法,因为在堆调整过程中可能会改变相同元素的相对位置。

- 适用于需要原地排序且对稳定性没有要求的情况。

 

堆排序在实践中通常用于对大规模数据进行排序,因为它不需要额外的空间,且具有较好的时间复杂度。然而,由于其不稳定性,当需要保持相同元素的相对位置不变时,可能需要考虑其他排序算法。以下是用 C++ 实现堆排序的示例代码:

 

```cpp

#include <iostream>

#include <vector>

 

// 调整堆,使其满足堆的性质
void heapify(std::vector<int>& arr, int n, int i) {
    int largest = i; // 初始化最大元素的下标
    int left = 2 * i + 1; // 左子节点的下标
    int right = 2 * i + 2; // 右子节点的下标
 
    // 如果左子节点大于根节点
    if (left < n && arr[left] > arr[largest]) {
        largest = left;
    }
 
    // 如果右子节点大于根节点
    if (right < n && arr[right] > arr[largest]) {
        largest = right;
    }
 
    // 如果最大元素的下标不是根节点下标,交换根节点和最大元素
    if (largest != i) {
        std::swap(arr[i], arr[largest]);
 
        // 递归调整子树
        heapify(arr, n, largest);
    }
}
 
// 堆排序
void heapSort(std::vector<int>& arr) {
    int n = arr.size();
 
    // 构建最大堆
    for (int i = n / 2 - 1; i >= 0; i--) {
        heapify(arr, n, i);
    }
 
    // 依次取出堆顶元素,将其放到数组末尾并调整堆
    for (int i = n - 1; i > 0; i--) {
        std::swap(arr[0], arr[i]); // 将堆顶元素与当前堆的最后一个元素交换
        heapify(arr, i, 0); // 调整堆
    }
}
 
void printArray(const std::vector<int>& arr) {
    for (int num : arr) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
}
 
int main() {
    std::vector<int> arr = {12, 11, 13, 5, 6, 7};
    int n = arr.size();
 
    std::cout << "Original array: ";
    printArray(arr);
 
    heapSort(arr);
 
    std::cout << "Sorted array: ";
    printArray(arr);
 
    return 0;
}
```

 

在这段代码中,`heapify` 函数用于调整堆,使其满足堆的性质。`heapSort` 函数实现了堆排序算法,包括构建最大堆和进行堆排序。`printArray` 函数用于打印数组的元素。在 `main` 函数中定义了一个整型数组并对其进行堆排序

相关文章
|
存储 算法 搜索推荐
C++实现排序 - 02 归并排序、快速排序和堆排序
今天我们继续来整理平均时间复杂度为 O(nlogn) 的三个排序算法,即归并排序、堆排序和快速排序。
272 0
C++实现排序 - 02 归并排序、快速排序和堆排序
|
7天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
33 4
|
8天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
27 4
|
1月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
27 4
|
1月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
23 4
|
1月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
21 1
|
1月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)
|
1月前
|
编译器 C++
【C++类和对象(中)】—— 我与C++的不解之缘(四)
【C++类和对象(中)】—— 我与C++的不解之缘(四)
|
1月前
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
53 1
|
1月前
|
编译器 C语言 C++
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
19 1