【笔记】堆排序
来源:互联网 发布:金庸 知乎 编辑:程序博客网 时间:2024/06/07 19:01
堆排序只需要记录一个记录大小的辅助空间,每个待排序的记录仅占有一个存储空间。
**堆的定义:**n个元素的序列
或
(i = 1,2,3,…,
若将和此序列对应的一维数组看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端节点的值均不大于其左、右孩子结点的值。由此,若序列
例如序列{96,83,27,38,11,09}和{12,36,24,85,47,30,53,91}对应的完全二叉树为:
若在输出堆顶的最小值之后,使得剩余n-1个元素的序列重又建成一个堆,则得到n个元素中的次小值。如此反复执行,便能得到一个有序序列,这个过程称之为堆排序。
- 调整堆
如下图所示,假设输出堆顶元素之后,以堆中最后一个元素替代,此时根结点的左、右子树均为堆,则仅需自上至下调整即可。首先以堆顶元素和其左、右子树根结点的值进行比较,由于右子树根结点的值相爱哦与左子树结点的值,则将27和97交换,由于97的替代了27之后破坏了右子树的堆,则需进行和上述相同的调整,直至叶子结点,此时堆顶为n-1个元素中的最小值。重复上述过程,将堆顶元素27和堆中最后一个元素97交换且调整,得到一个新的堆。我们称这个自堆顶至叶子的调整过程为筛选。
- 建堆
从一个无序序列建堆的过程就是一个反复筛选的过程。若将次序列看成是一个完全二叉树,则最后一个非终端结点是第
例如下图中的二叉树表示一个有8个元素的无序序列{49,38,65,97,76,13,27,49},则筛选从第4个元素开始,由于97>49,则交换之。同理,在第3个元素65被筛选之后序列的状态如图所示。由于第2个元素38不大于其左、右子树根的值,则筛选后的序列不变。
基本算法思想:使记录序列按关键字非递减有序排列,则在堆排序的算法中先建立一个最大堆,即先选得一个关键字为最大的记录并与序列中最后一个记录交换,然后对序列中前n-1记录进行筛选,重新将它调整为一个最大堆,如此分那副直至排序结束。
- 类型定义
#include<stdio.h> #define EQ(a,b) ((a)==(b)) #define LT(a,b) ((a)<(b)) #define LQ(a,b) ((a)<=(b)) #define N 8 #define MAXSIZE 20 /* 一个用作示例的小顺序表的最大长度 */ typedef int InfoType; /* 定义其它数据项的类型 */ typedef int KeyType; /* 定义关键字类型为整型 */ typedef struct { KeyType key; /* 关键字项 */ InfoType otherinfo; /* 其它数据项,具体类型在主程中定义 */ }RedType; /* 记录类型 */ typedef struct { RedType r[MAXSIZE+1]; /* r[0]闲置或用作哨兵单元 */ int length; /* 顺序表长度 */ }SqList; /* 顺序表类型 */ typedef SqList HeapType; /* 堆采用顺序表存储表示 */
- 堆排序函数
void HeapAdjust(HeapType *H,int s,int m) /* 算法10.10 */ { /* 已知H.r[s..m]中记录的关键字除H.r[s].key之外均满足堆的定义,本函数 */ /* 调整H.r[s]的关键字,使H.r[s..m]成为一个大顶堆(对其中记录的关键字而言) */ RedType rc; int j; rc=(*H).r[s]; for(j=2*s;j<=m;j*=2) { /* 沿key较大的孩子结点向下筛选 */ if(j<m&<((*H).r[j].key,(*H).r[j+1].key)) ++j; /* j为key较大的记录的下标 */ if(!LT(rc.key,(*H).r[j].key)) break; /* rc应插入在位置s上 */ (*H).r[s]=(*H).r[j]; s=j; } (*H).r[s]=rc; /* 插入 */ } void HeapSort(HeapType *H) { /* 对顺序表H进行堆排序。算法10.11 */ RedType t; int i; for(i=(*H).length/2;i>0;--i) /* 把H.r[1..H.length]建成大顶堆 */ HeapAdjust(H,i,(*H).length); for(i=(*H).length;i>1;--i) { /* 将堆顶记录和当前未经排序子序列H.r[1..i]中最后一个记录相互交换 */ t=(*H).r[1]; (*H).r[1]=(*H).r[i]; (*H).r[i]=t; HeapAdjust(H,1,i-1); /* 将H.r[1..i-1]重新调整为大顶堆 */ } }
- 主程序
void print(HeapType H) { int i; for(i=1;i<=H.length;i++) printf("(%d,%d)",H.r[i].key,H.r[i].otherinfo); printf("\n"); } void main() { RedType d[N]={{49,1},{38,2},{65,3},{97,4},{76,5},{13,6},{27,7},{49,8}}; HeapType h; int i; for(i=0;i<N;i++) h.r[i+1]=d[i]; h.length=N; printf("排序前:\n"); print(h); HeapSort(&h); printf("排序后:\n"); print(h); }
- 测试结果
- 【数据结构】堆、堆排序笔记
- 堆排序学习笔记
- 算法笔记--堆排序
- 堆排序学习笔记
- 学习笔记--堆排序
- 堆排序算法笔记
- 算法笔记-堆排序
- 堆排序笔记
- 【笔记】堆排序
- Python笔记:二叉堆及堆排序
- 《数据结构复习笔记》--堆和堆排序
- 最大堆和堆排序学习笔记
- 算法导论笔记,堆排序
- 算法学习笔记----堆排序
- Algorithm学习笔记 --- 堆排序
- 算法笔记之堆排序
- 算法笔记之堆排序
- 算法学习笔记--堆排序
- 【1701H1】【穆晨】【171111】连续第三十二天总结
- STL算法-归并和最大最小值算法
- C++MFC窗体和Dos命令窗口中如何使用字符串
- wait(long timeout)
- 图像基础22 运动侦测
- 【笔记】堆排序
- Servlet(2)
- Java设计模式百例
- Access时间转换
- JS实现在不知道盒子宽高的情况下,默认让盒子在页面中水平垂直居中
- Toolbar的简单使用和封装
- access数据库语句
- 封装模型成员变量
- 自然场景下OCR---Andrew Ng组论文