堆排序(Heapsort)

复杂度: O(nlog(n))
堆是一个数组,可以看做近似的完全二叉树;

对于给定的下标 i :
父节点的下标:i/2
左子节点的下标:2i
右子节点的下标:2i+1

最大堆:

除了根以外的结点满足:

a[Parent(i)] >= a[i]

维护堆的性质:
宏定义:

# define PARENT(i) (i/2)
# define LEFT(i) (2*i)
# define RIGHT(i) (2*i + 1)

多说一句,这里如果用堆排序的话,下标要从1开始了,因为如果i是0,LEFT(i)也是0,而左子节点应该是1,就会出现错误,所以数组下标的范围为 1 到 heap_size

MAX-HEAPIFY函数:

void MaxHeapify(int* a, int i, int heap_size) {
    int maxn = i;
    if (LEFT(i) <= heap_size && a[LEFT(i)] > a[i]) {
        maxn = LEFT(i); 
    }
    if (RIGHT(i) <= heap_size && a[RIGHT(i)] > a[maxn]) {
        maxn = RIGHT(i);
    }
    if (maxn != i) {
        swap(a[i], a[maxn]);    
        MaxHeapify(a, maxn, heap_size);
    }
}

程序第9行,如果我们一开始就是一个局部的最大堆,就满足第一个元素最大,我们是不会递归向下去维护堆的性质的

建堆:
a[(n/2)+1]到a[n-1]的元素是叶子节点;
对所有非叶子节点,调用一次MaxHeapify():

void BuildMaxHeap(int* a, int heap_size) {
    for (int i = heap_size / 2; i >= 0; i--)
        MaxHeapify(a, i, heap_size);
}

复杂度:
这里直观理解的话,建一个最大堆貌似是 O(nlog(n))
但是经过P88的运算就神奇变成了 O(n)

堆排序:

void HeapSort(int* a, int heap_size) {
    BuildMaxHeap(a, heap_size);
    for (int i = heap_size; i > 1; i--) {
        swap(a[1], a[i]);
        heap_size--;
        MaxHeapify(a, 1, heap_size);
    }
}

优先队列:

四种操作:

INSERT(S,x):把元素x插入到S中
MAXIMUM(S):返回S中具有最大键字的元素
EXTRACT-MAX(S):去掉并返回S中具有最大键字的元素
INCREASE-KEY(S,x,k):将元素x的关键字值增加到k, 这里假设k的值不小于x的原关键字值

MAXIMUM(S):

int HeapMaximum(int* a) {
    return a[1];
}

EXTRACT-MAX(S):

int HeapExtractMax(int* a, int heap_size) {
    if (heap_size < 1) {
        cout << "Heap Underflow\n";
        return;
    }
    int maxn = a[1];
    a[1] = a[heap_size];
    heap_size --;
    MaxHeapify(a, 1);
    return maxn;
}

INCREASE-KEY(S,x,k):

void HeapIncreaseKey(int* a, int i, int k) {
    if (k < a[i]) {
        cout << "Wrong Input\n";
        return;
    }
    a[i] = k;
    while(i > 1 && a[PARENT(i)] > a[i]) {
        swap(a[i], a[PARENT(i)]);
        i = PARENT(i);
    }
}

INSERT(S,x):
先开一个节点在优先队列的末尾,关键字赋为负无穷,然后将这个节点的关键字增加到x

void MaxHeapInsert(int* a, int x, int heap_size) {
    heap_size = heap_size + 1;  //这里要保证不会溢出
    a[heap_size] = -MAXN;
    HeapIncreaseKey(a, heap_size, x);
}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看rEADME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看rEADME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值