堆排序及代码实现

这几天有点抵触情绪,看过了快速排序还有一些别的东西,但是一点都不想写有点复杂的代码0 0拖到了今天终于写了前几天就应该自己写一下的堆排序,完全用C语言写的,下面把代码贴一下。很多地方写得并不好,不过已经经过了测试,可以正确运行。

 1 /*堆排序*/
 2 void percolateDown(int* A, int i, int n)//下滤操作
 3 {
 4     while (i <= ((n - 1) - 1) / 2)
 5     {
 6         int rc = 2 * i + 2, lc = 2 * i + 1;
 7         if (rc < n)//如果右孩子存在
 8         {
 9             int j = ((A[rc] > A[i]) ? ((A[rc] > A[lc]) ? rc : lc) : ((A[lc] > A[i]) ? lc : i));
10             if (i == j) break;
11             swap(A[j], A[i]);
12             i = j;
13         }
14         else if(lc < n)//仅有左孩子(只有最后一个内部节点可能会这种情况)
15         {
16             if (A[i] >= A[lc]) break;
17             if (A[i] < A[lc])
18             {
19                 swap(A[i], A[lc]);
20                 i = lc;
21             }
22         }
23         else
24             break;
25     }
26 }
27 void buildHeap(int* A, int n)//将数组就地建堆
28 {
29     for (int i = ((n - 1) - 1) / 2; (i >= 0) && (i < n); i--)//从最后一个内部节点的位置开始
30         percolateDown(A, i, n);
31 }
32 int delMax(int* A,int n)//删除最大元素,调用者自行更改规模
33 {
34     int max = A[0];
35     A[0] = A[n - 1];
36     percolateDown(A, 0, n - 1);
37     return max;
38 }
39 void heapSort(int* A, int n)//堆排序主算法
40 {
41     buildHeap(A, n);//就地建堆
42     while(n > 0)
43     {
44         A[n - 1] = delMax(A, n);//等价于交换未排序序列的末元素与堆顶最大元素
45         n--;
46     }
47 }

建堆是最为关键的环节,可以说堆建好了才能开始进行排序。这里为了保持高效,建堆采用的是Floyd就地建堆算法,就是从原数组最后一个内部节点的位置进行下滤操作,当下滤到外部节点或x,x->lc,x->rc节点中最大的就是x节点时,下滤结束,继续进行下一个节点的下滤。每次交换元素后,新的堆顶并不是一个合格的堆顶,因此需要对堆顶继续进行下滤操作,不过注意到,只有堆顶一个节点是不合适的,所以重新建堆的操作复杂度不超过O(logn),即堆的高度。

后面可能还会写一个K-选取的问题,即选取数组中第K大的元素,或者选取前K大的元素这种问题。基于优先级队列的方法,是一个可行的解,不过最坏情况的复杂度并不让人满意。

时间: 2024-08-02 11:04:40

堆排序及代码实现的相关文章

堆排序【代码】

思路参考<算法导论>P84 堆排序中用到的最重要的就是堆这种数据结构,也正是因为这种数据结构能把时间复杂度控制在O(n * lgn) heapsort算法主要依赖于两个函数 MAX_HEAPIFY(int *A,int i,int len) 用于维护最大堆,时间复杂度为O(lgn),注意书上描述这个函数的算法只用了两个形参,而由于C++无法通过指针获取数组的大小,所以我额外添加了一个参数作为数组的大小 BUILD_MAX_HEAP(int *A,int len) 从无序的输入数据数组中构造一个

堆排序讲解(代码简洁)

//本文适用于对堆排序部分理解的同学,主要体现的是代码的简洁. /*算法思想(以大顶堆为例):      1.将长度为n的待排序的数组进行堆有序化构造成一个大顶堆      2.将根节点与尾节点交换并输出此时的尾节点      3.将剩余的n -1个节点重新进行堆有序化      4.重复步骤2,步骤3直至构造成一个有序序列*/ //堆排序public class HeapSort {    public static void heapSort(int arr[]){        int s

Java排序算法 - 堆排序的代码

把内容过程中比较重要的一些内容片段做个备份,如下的资料是关于Java排序算法 - 堆排序的内容. import java.util.Arrays; public class HeapSort { int a[]={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35,25,53,51}; public HeapSort(){ heapSort(a); } public void heapSort(int[

堆排序(代码1)

#include <stdio.h> #include <stdlib.h> void build_heap(int data[], int); void adjust_heap(int data[], int); void heap_sort(int data[], int); int sub_max_heap(int data[], int, int); int main(int argc, char *argv[]) { int i; int data[12] = {6, 1

堆排序(代码2)

1 #include <stdio.h> 2 #include <stdlib.h> 3 4 void build_heap(int data[], int); 5 void adjust_heap(int data[], int); 6 void heap_sort(int data[], int); 7 int sub_max_heap(int data[], int, int); 8 9 int main(int argc, char *argv[]) 10 { 11 int

算法导论学习之堆+堆排序+堆构成优先队列

注:堆分为最大堆和最小堆两种,下面我们讨论的堆都是指的最大堆,最小堆的性质与其是类似的. 堆数据结构是一种数组对象,可以被视为一棵完全二叉树(这棵二叉树除最后一层外,其余每层都是填满的):我们用一个数组来存储一个堆,表示堆的数组有两个属性:length[A]表示的是数组中的元素个数,headsize[A]表示堆中元素个数(也就是说数组中的元素不一定都是堆中的元素). 下面不加证明的给出一些堆的性质: 对于任何一个节点,其父节点为i/2(i>1):左儿子:2*i,右儿子:2*i+1; 对于最大堆每

排序算法之堆排序

1. 堆排序的思想 输入一个数组,利用一组二叉树的操作使其变成有序的数组,就是堆排序 堆排序利用的是二叉树的思想,操作对象是数组,所以数组需要在逻辑上映射到二叉树上,由于数组的下标是连续的,而二叉树中只有完全二叉树和满二叉树是连续的,所以将数组元素逐个映射到完全二叉树上,然后配备一系列的操作即可.例如数组data[]={9,6,5,4,3,2,1,7},映射到完全二叉树上如下图所示. 2.堆排序的过程 还是用上面的data数组作为输入数组,映射到完全二叉树如上图所示,怎么利用二叉树的性质,才能使

堆排序——深入浅出(图解)

如何建立这个堆呢.可以从空的堆开始,然后依次往堆中插入每一个元素,直到所有数都被插入(转移到堆中为止).因为插入第i个元素的所用的时间是O(log i),所以插入所有元素的整体时间复杂度是O(NlogN),代码如下. n=0; for(i=1;i<=m;i++) { n++; h[ n]=a[ i]; //或者写成scanf("%d",&h[ n]); siftup(); } 其实我们还有更快得方法来建立堆.它是这样的. 直接把99.5.36.7.22.17.46.12.

算法分析之——heap-sort堆排序

堆排序是一种原地排序排序算法,不使用额外的数组空间,运行时间为O(nlgn).本篇文章我们来介绍一下堆排序的实现过程. 要了解堆排序,我们首先来了解一个概念,完全二叉树.堆是一种完全二叉树或者近似完全二叉树.什么是完全二叉树呢?百度百科上给出定义:完全二叉树:除最后一层外,每一层上的节点数均达到最大值:在最后一层上只缺少右边的若干结点.下面用两个小图来说明完全二叉树与非完全二叉树.(图片来自百度,大家可以忽略水印-..) 二叉堆满足二个特性: 1.父结点的键值总是大于或等于(小于或等于)任何一个