C++堆排序算法的实现方法_C 语言

 本文实例讲述了C++实现堆排序算法的方法,相信对于大家学习数据结构与算法会起到一定的帮助作用。具体内容如下:

 首先,由于堆排序算法说起来比较长,所以在这里单独讲一下。堆排序是一种树形选择排序方法,它的特点是:在排序过程中,将L[n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲节点和孩子节点之间的内在关系,在当前无序区中选择关键字最大(或最小)的元素。

一、堆的定义

堆的定义如下:n个关键字序列L[n]成为堆,当且仅当该序列满足:
①L(i) <= L(2i)且L(i) <= L(2i+1)  或者  ②L(i) >= L(2i)且L(i) >= L(2i+1)   其中i属于[1, n/2]。

满足第①种情况的堆称为小根堆(小顶堆),满足第②种情况的堆称为大根堆(大顶堆)。在大根堆中,最大元素存放在根结点中,且对任一非根结点,它的值小于或等于其双亲结点值。小根堆则恰恰相反,小根堆的根结点存放的是最小元素。例如{16, 14, 10, 8, 7, 9, 3, 2}表示的大根堆:

                                 

二、构造初始堆

堆排序的关键就是构造初始堆。n个结点的完全二叉树中,最后一个结点是第n/2(向下取整)个结点的孩子。所以构造初始堆的流程是:对第n/2(向下取整)个结点为根的子树进行筛选(以大根堆为例,若根结点的关键字小于左右子女中关键字的较大者,则交换),使该子树成为堆。之后向前依次对从n/2-1到1的各结点为根的子树进行筛选,看该结点值是否大于其左右子结点的值,若不是,将左右子结点中较大值与之交换,交换后可能会破坏下一级的堆,于是继续采用上述方法构造下一级的堆,直到以该结点为根的子树构成堆为止。反复利用上述调整堆的方法建堆,直到根结点。

由于在数组中下标从0开始,所以在堆中i的左子结点为2*i+1,右子结点为2*i+2。下面是将某个结点i向下调整建堆的算法实现:

void AdjustDown(ElementType A[], int i, int len)
{
  ElementType temp = A[i]; // 暂存A[i] 

  for(int largest=2*i+1; largest<len; largest=2*largest+1)
  {
    if(largest!=len-1 && A[largest+1]>A[largest])
      ++largest;     // 如果右子结点大
    if(temp < A[largest])
    {
      A[i] = A[largest];
      i = largest;     // 记录交换后的位置
    }
    else
      break;
  }
  A[i] = temp;  // 被筛选结点的值放入最终位置
} 

 

建堆,从n/2(向下取整)到1依次对各结点向下调整,当然由于数组下标从0开始,所以:

void BuildMaxHeap(ElementType A[], int len)
{
  for(int i=len/2-1; i>=0; --i) // 从i=n/2-1到0,反复调整堆
    AdjustDown(A, i, len);
} 

三、堆排序

构造初始堆成功以后,堆排序的思路就很简单了:首先将存放在L[n]中的n个元素建成初始堆,由于堆本身的特点(以大根堆为例),堆顶元素就是最大值。输出堆顶元素后,通常将堆底元素送入堆顶,此时根结点已不满足大根堆的性质,堆被破坏。这时将堆顶元素向下调整使其继续保持大根堆的性质,再输出堆顶元素。如此重复,直到堆中仅剩下一个元素为止。算法实现如下:

void HeapSort(ElementType A[], int n)
{
  BuildMaxHeap(A, n);    // 初始建堆
  for(int i=n-1; i>0; --i) // n-1趟的交换和建堆过程
  {
    // 输出最大的堆顶元素(和堆底元素交换)
    A[0] = A[0]^A[i];
    A[i] = A[0]^A[i];
    A[0] = A[0]^A[i];
    // 调整,把剩余的n-1个元素整理成堆
    AdjustDown(A, 0, i);
  }
} 

四、性能分析

时间复杂度:向下调整的时间与树高有关,为O(h)。可以证明在元素个数为n的序列上建堆,其时间复杂度为O(n)。之后还有n-1次向下调整操作,每次调整的时间为O(h),故在最好,最坏和平均情况下,堆排序的时间复杂度为O(nlogn)。

空间复杂度:仅使用了常数个辅助单元,空间复杂度为O(1)。

稳定性:不稳定。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索c++
, 算法
堆排序
堆排序算法c语言、堆排序算法实现、堆排序原理及算法实现、堆排序c语言实现、汇编语言实现堆排序,以便于您获取更多的相关知识。

时间: 2024-09-20 05:42:07

C++堆排序算法的实现方法_C 语言的相关文章

排列和组合算法的实现方法_C语言经典案例_C 语言

排列和组合算法是考查递归的常见算法,这两种算法能用递归简洁地实现. 本人在经过多次摸索和思考之后,总结如下,以供参考. 程序代码如下: #include <stdio.h> #include <stdlib.h> char array[] = "abcd"; #define N 4 #define M 3 int queue[N] = {0}; int top = 0; int flag[N] = {0}; void perm(int s, int n) { i

7种排序算法的实现示例_C 语言

复制代码 代码如下: #include <stdio.h>#include <stdlib.h>#include <time.h> void BubbleSort1 (int n, int *array) /*little > big*/{ int i, j; for (i=0; i<n-1; i++) {  for (j=n-1; j>i; j--)  {   if (array[j] < array[j-1])   {    int temp

C++火车入轨算法的实现代码_C 语言

[问题描述] 某城市有一个火车站,铁轨铺设如图所示.有n节车厢从A方向驶入车站,按进站顺序编号为1~n.你的任务是让它们按照某种特定的顺序进入B方向的铁轨并驶出车站.为了重组车厢,你可以借助中转站C.这是一个可以停放任意多节车厢的车站,但由于末端封顶,驶入C的车厢必须按照相反的顺序驶出.对于每个车厢,一旦从A移入C,就不能再回到A了:一旦从C移入B,就不能回到C了.换句话说,在任意时刻,只有两种选择:A→C和C→B. 这个问题和之前数据结构实验的火车入轨类似,而且较之简化.自己尝试写了下,和书上

php仿微信红包分配算法的实现方法_php技巧

本文实例讲述了php仿微信红包分配算法的实现方法.分享给大家供大家参考,具体如下: /** * 红包分配:把一定金额随机分配给指定人数 * * @param int $money 用于分配的金额 * @param int $num 分配人数 */ function RandomMoney($money, $num) { echo "$money元随机分成$num份分别是:<br/>"; $remain=$money; $use=0; for ($i=1; $i<$nu

C++实现合并排序的方法_C 语言

本文实例讲述了C++实现合并排序的方法.分享给大家供大家参考.具体如下: //合并排序 #include<iostream> #include<cmath> using namespace std; int num[100]; void print(int num[],int len) { for(int i=0;i<len;i++) { cout<<num[i]<<" "; } cout<<endl; } void m

使用C语言解决字符串匹配问题的方法_C 语言

最常想到的方法是使用KMP字符串匹配算法: #include <stdio.h> #include <stdlib.h> #include <string.h> int get_nextval(char *pattern, int next[]) { //get the next value of the pattern int i = 0, j = -1; next[0] = -1; int patlen = strlen(pattern); while ( i &l

C语言中读取时间日期的基本方法_C 语言

C语言time()函数:获取当前时间(以秒数表示)头文件: #include <time.h> 定义函数: time_t time(time_t *t); 函数说明:此函数会返回从公元 1970 年1 月1 日的UTC 时间从0 时0 分0 秒算起到现在所经过的秒数.如果t 并非空指针的话,此函数也会将返回值存到t 指针所指的内存. 返回值:成功则返回秒数,失败则返回((time_t)-1)值,错误原因存于errno 中. 范例 #include <time.h> main(){

使用C语言实现CRC校验的方法_C 语言

CRC(Cyclic Redundancy Check)校验应用较为广泛,以前为了处理简单,在程序中大多数采用LRC(Longitudinal Redundancy Check)校验,LRC校验很好理解,编程实现简单.用了一天时间研究了CRC的C语言实现,理解和掌握了基本原理和C语言编程.结合自己的理解简单写下来. 1.CRC简介 CRC检验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个检验码r位(就是CRC码),附在信息后面,构成一个新的二进制码序列数

使用WindowsAPI获取录音音频的方法_C 语言

本文实例介绍了使用winmm.h进行音频流的获取的方法,具体步骤如下: 一.首先需要包含以下引用对象 #include <Windows.h> #include "mmsystem.h" #pragma comment(lib, "winmm.lib") 二.音频的获取需要调用7个函数 1. waveInGetNumDevs:返回系统中就绪的波形声音输入设备的数量 UINT waveInGetNumDevs(VOID); 2. waveInGetDevC