C语言数据结构之堆排序的优化算法

C语言数据结构之堆排序的优化算法攻略

堆排序简介

堆排序(HeapSort)是一种树形选择排序,在排序过程中始终保持一个最大堆,每次将堆顶元素与最后一个元素交换位置,并进行一次最大堆调整操作,直到整个序列有序为止。

堆排序的时间复杂度为O(nlogn),具有不需额外存储空间的特点,因此广泛应用于内存受限的场景。

堆排序的优化算法

1. 建堆操作的优化

将序列中的元素插入到空堆中,时间复杂度为O(nlogn),可以通过优化建堆操作,将其时间复杂度降至O(n)。

建堆操作的本质是将序列中的元素依次插入到堆中,因此可以考虑一次性将序列中的所有元素插入到堆中。具体方法如下:

void buildHeap(int a[], int n) {
    int i;
    for (i = n / 2; i >= 1; i--) {
        heapify(a, i, n);
    }
}

由于完全二叉树中叶子节点占据了一半的空间,因此从第n/2个节点开始(包括第n/2个节点)是堆中所有非叶子节点。从第n/2个节点开始,从后往前依次执行heapify操作,即每次将当前节点和其子节点进行比较并进行调整。由于叶子节点不需要调整,因此可以忽略叶子节点,将操作次数降至一半。

2. 堆调整操作的优化

堆调整操作的本质是将某个节点的值减小,从而可能影响到该节点的子节点,需要依次将该节点与其子节点进行比较,对不满足堆性质的节点进行调整。由于每次调整只是将节点移动到正确的位置,因此可以考虑将堆调整操作优化为插入操作。

具体方法如下:

void heapInsert(int a[], int n, int k) {
    int cur = n;
    a[cur] = k;
    while (cur > 1 && k > a[cur / 2]) {
        a[cur] = a[cur / 2];
        cur /= 2;
    }
    a[cur] = k;
}

每次将堆的最后一个元素插入到堆中,由于插入元素的大小可能会影响到堆的调整,因此需要按照子节点的大小依次将该元素与其父节点进行比较。如果插入元素比父节点大,则将父节点移动到当前位置,并将当前位置改为父节点,继续向上比较。最后将插入元素插入到正确的位置。

示例1

#include <stdio.h>

void heapify(int a[], int i, int n) {
    int max = i, l = 2 * i, r = l + 1;
    if (l <= n && a[l] > a[max]) {
        max = l;
    }
    if (r <= n && a[r] > a[max]) {
        max = r;
    }
    if (max != i) {
        int temp = a[i];
        a[i] = a[max];
        a[max] = temp;
        heapify(a, max, n);
    }
}

void heapSort(int a[], int n) {
    int i;
    for (i = n / 2; i >= 1; i--) {
        heapify(a, i, n);
    }
    for (i = n; i > 1; i--) {
        int temp = a[1];
        a[1] = a[i];
        a[i] = temp;
        heapify(a, 1, i - 1);
    }
}

int main() {
    int a[] = {0, 5, 2, 4, 1, 3};
    int n = sizeof(a) / sizeof(int) - 1;
    heapSort(a, n);
    int i;
    for (i = 1; i <= n; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}

执行结果:

1 2 3 4 5

示例2

#include <stdio.h>

void heapInsert(int a[], int n, int k) {
    int cur = n;
    a[cur] = k;
    while (cur > 1 && k > a[cur / 2]) {
        a[cur] = a[cur / 2];
        cur /= 2;
    }
    a[cur] = k;
}

int main() {
    int a[10] = {0};
    int n = 0;
    heapInsert(a, ++n, 5);
    heapInsert(a, ++n, 1);
    heapInsert(a, ++n, 4);
    heapInsert(a, ++n, 2);
    heapInsert(a, ++n, 3);
    int i;
    for (i = 1; i <= n; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}

执行结果:

5 3 4 1 2

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构之堆排序的优化算法 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • Python实现的数据结构与算法之双端队列详解

    Python实现的数据结构与算法之双端队列详解 什么是双端队列? 双端队列是一种具有队列和栈的性质的数据结构,可以在队列两端进行插入和删除操作。双端队列可以实现两端的操作,因此可以在队列两端进行插入和删除操作,既可以像队列一样先进先出,也可以像栈一样后进先出。 双端队列的操作 add_front(item):在队头插入一个元素; add_rear(item)…

    数据结构 2023年5月17日
    00
  • C语言线性表的链式表示及实现详解

    C语言线性表的链式表示及实现详解 什么是线性表 线性表是一种在计算机科学中常见的数据结构,它由一组连接在一起的元素组成,每个元素都包含前后指针以指向相邻的元素,从而构成一个连续的线性序列。线性表可以用来存储和处理一般数据集合。 链式存储结构 线性表的链式存储结构是由若干个结构体组成的链表,每个结构体都称为一个节点。每个节点包含两个字段:一个数据域用来存放数据…

    数据结构 2023年5月17日
    00
  • 实际问题中用到的算法——递归算法确定插帧顺序

    问题: 现在需要给一个视频序列插帧,插帧算法要求每次只能由两帧输入插值得到其中间帧。如果现在需要给一个视频做 4 倍(或者更高的 8,16 倍等类似)的插帧,则一个插帧的思路是当前视频每相邻帧之间插入 3 帧,即:假设插帧前视频帧序号是 0,4,8,12…,则插帧时补充相邻帧跨过的 3 个序号,得到插帧后的视频帧序号为 0,1,2,3,4,5,6,.. 即可…

    算法与数据结构 2023年4月18日
    00
  • C语言线性表之双链表详解

    C语言线性表之双链表详解 前言 本教程将详细介绍C语言中双链表的实现方法以及相关操作,适合有一定C语言基础的读者。 双链表定义 双链表是一种常见的数据结构,与单链表不同,双链表中每个节点不仅有指向后续节点的指针,还有指向前续节点的指针,即“双向链表”。 双链表的节点结构体可以定义如下: typedef struct double_node{ int data…

    数据结构 2023年5月17日
    00
  • Python内存管理器如何实现池化技术

    Python内存管理器使用了池化技术来进行内存管理,这使得Python程序的内存管理效率比较高。下面我将详细介绍Python内存管理器如何实现池化技术: 1. 内存分配 Python内存管理器在Python运行时,会维护多个大小不同的内存块池,每个池的大小相同。当Python程序需要分配内存时,会首先在池中寻找是否有剩余内存块可以分配。如果有,则分配给程序使…

    数据结构 2023年5月17日
    00
  • 自学1

    Problem1 明明的随机数 ## 题目描述 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了 N 个 1 到 1000 之间的随机整数 (N <= 100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“…

    算法与数据结构 2023年4月24日
    00
  • Java concurrency集合之LinkedBlockingDeque_动力节点Java学院整理

    Java Concurrency集合之LinkedBlockingDeque_动力节点Java学院整理 LinkedBlockingDeque是什么? LinkedBlockingDeque是java.util.concurrent包下一个双向阻塞队列,用于在多线程的环境中处理元素序列,它支持在队列两端添加和移除元素。LinkedBlockingDeque可…

    数据结构 2023年5月17日
    00
  • 如何配置git环境

    首先我们新建一个文件夹;    然后我们右键git Bash Here一下;在里面输入: cd ssh-keygen cd.ssh ls (注意,我们要是之前就生成过密钥,直接输入ls就好了) 输入ls之后,会显示出来我们的公钥,我们输入: cat id_rsa.pub 然后密钥就出来了,密钥出来之后,我们把密钥复制一下,打开github 选择设置; 中会有…

    算法与数据结构 2023年4月18日
    00
合作推广
合作推广
分享本页
返回顶部