目录

  • 《算法笔记》重点摘要
  • 1147 Heaps (30)
  • 1155 Heap Paths (30)

《算法笔记》 9.7 堆 重点摘要

1. 定义

堆是完全二叉树,树中每个结点的值不小于(或不大于)其左右子结点的值,称之为大顶堆(或小顶堆)

const int maxn = 100;
int heap[maxn], n = 10; // heap 为堆,n 为元素个数

2. 向下调整

// 对 heap 数组在 [low,high] 范围进行向下调整
// 其中 low 为欲调整结点的数组下标, high 一般为堆的最后一个元素的数组下标
void downAdjust(int low, int high){
int i = low, j = i * 2; // i 为欲调整结点,j 为其左子结点
while (j <= high){ // 存在子结点时进行循环
if (j + 1 <= high && heap[j+1] > heap[j) // 若右子结点存在且值大于左子结点
j = j + 1;
if (heap[j] > heap[i]){ // 若子结点中最大的值比欲调整结点 i 的值大
swap(heap[j], heap[i]);
i = j;
j = i * 2;
// 保持 i 为欲调整结点,j 为其左子结点
}
else break;
}
}

3. 建堆

  • 完全二叉树叶子结点数为 ceil(n/2)
  • 数组下标在 [1,floor(n/2)] 内均为非叶子节点
  • 从 floor(n/2) 开始倒着枚举结点,对每个结点 i 进行 [i,n] 范围调整
  • 保证每个节点都是以其为根结点的子树中值最大的结点
void createHeap(){
for (int i = n / 2; i >= 1; i--)
downAdjust(i,n);
}

4. 删除堆顶元素

用最后一个元素覆盖堆顶元素,再对根结点进行调整

void deleteTop(){
heap[1] == heap[n--]; // 覆盖后元素个数 --
downAdjust(1,n);
}

5. 向上调整

// 对 heap 数组在 [low,high] 范围进行向上调整
// 其中 low 一般设置为 1, high 为欲调整结点的数组下标
void upAdjust(int low, int high){
int i = high, j = i / 2; // i 为欲调整结点,j 为其父结点
while (j >= low){ // 父结点在 [low,high] 范围内
if (heap[j] < heap[i]){ // 父结点值小于欲调整结点值
swap(heap[j],heap[i]);
i = j;
j = i / 2;
// 保持i 为欲调整结点,j 为其父结点
}
else break;
}
}

6. 添加元素

void insert(int x){
heap[++n] = x;
upAdjust(1,n);
}

7. 堆排序

  • 倒着遍历数组
  • 访问到 i 位置时,将堆顶元素与 i 位置元素交换,则 i 位置固定为 [1,i] 最大值
  • 在 [1,i-1] 范围对堆顶元素进行向下调整
void heapSort(){
createHeap();
for (int i = n; i > 1; i++){
swap(heap[i], heap[1]);
downAdjust(1, i-1);
}
}

8. 递推判断堆类型方法

bool isMax = true, isMin = true;
for (int i = 2; i <= n; i++) {
if (tree[i/2] > tree[i]) isMin = false;
if (tree[i/2] < tree[i]) isMax = false;
}
printf("%s\n", isMax ? "Max Heap" : isMin ? "Min Heap" : "Not Heap");

1147 Heaps (30)

题目思路

  • 递推 判断堆类型,两个变量分别记录是否符合大顶堆 / 小顶堆
  • 递归 保存后序遍历序列,按要求输出,注意每检查一个新的堆要将保存后序序列的容器清空 post.clear()
#include<iostream>
#include<vector>
using namespace std;
int n;
vector<int> tree, post;
void postorder(int index){
if (index > n) return;
postorder(index * 2);
postorder(index * 2 + 1);
post.push_back(tree[index]);
}
int main()
{
int m, data;
scanf("%d%d", &m, &n);
tree.resize(n+1);
for (int i = 0; i < m; i++){
for (int j = 1; j < n + 1; j++) scanf("%d", &tree[j]);
bool isMax = true, isMin = true;
for (int j = 2; j < n + 1; j++){
if (tree[j/2] > tree[j]) isMin = false;
if (tree[j/2] < tree[j]) isMax = false;
}
printf("%s\n", isMax ? "Max Heap" : isMin ? "Min Heap" : "Not Heap");
post.clear();
postorder(1);
for (int j = 0; j < post.size(); j++)
printf("%d%c", post[j], j + 1 == post.size() ? '\n' : ' ');
}
return 0;
}

1155 Heap Paths (30)

题目思路

  • DFS 递归 输出路径

    • 终止条件:到叶结点(2 * index > n),输出路径
    • 进入下一层条件:下一层的子结点存在
    • 即递归确认下一个结点存在时才进入,能进入递归的都是存在非越界的结点,所以通过其子结点越界判断到叶结点,输出到此结点的路径
  • 递归 判断是什么堆
    • 每进入一个非根节点的结点,就判断它与父结点的大小关系
    • 不符合大顶堆或小顶堆的就将对应变量置 false,符合要求的没有机会被置 false
    • 最后根据变量输出判断结果
#include<iostream>
#include<vector>
using namespace std;
int n, tree[1001];;
bool isMax = true, isMin = true;
vector<int> path;
void DFS(int index){
if (index > 1){
if (tree[index] > tree[index/2]) isMax = false;
if (tree[index] < tree[index/2]) isMin = false;
}
if (2 * index > n){
for (int i = 0; i < path.size(); i++)
printf("%d%c", tree[path[i]], i == path.size()-1 ? '\n' : ' ');
return;
}
if (2 * index + 1 <= n){
path.push_back(2 * index + 1);
DFS(2 * index + 1);
path.pop_back();
}
path.push_back(2 * index);
DFS(2 * index);
path.pop_back();
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &tree[i+1]);
path.push_back(1);
DFS(1);
printf("%s\n", isMax ? "Max Heap" : isMin ? "Min Heap" : "Not Heap");
return 0;
}

PAT甲级 堆 相关题_C++题解的更多相关文章

  1. PAT甲级 Dijkstra 相关题_C++题解

    Dijkstra PAT (Advanced Level) Practice Dijkstra 相关题 目录 <算法笔记>重点摘要 1003 Emergency (25) <算法笔记 ...

  2. PAT甲级 二叉树 相关题_C++题解

    二叉树 PAT (Advanced Level) Practice 二叉树 相关题 目录 <算法笔记> 重点摘要 1020 Tree Traversals (25) 1086 Tree T ...

  3. PAT甲级 二叉查找树 相关题_C++题解

    二叉查找树 PAT (Advanced Level) Practice 二叉查找树 相关题 目录 <算法笔记> 重点摘要 1099 Build A Binary Search Tree ( ...

  4. PAT甲级 图 相关题_C++题解

    图 PAT (Advanced Level) Practice 用到图的存储方式,但没有用到图的算法的题目 目录 1122 Hamiltonian Cycle (25) 1126 Eulerian P ...

  5. PAT甲级 树 相关题_C++题解

    树 目录 <算法笔记>重点摘要 1004 Counting Leaves (30) 1053 Path of Equal Weight (30) 1079 Total Sales of S ...

  6. PAT甲级 散列题_C++题解

    散列 PAT (Advanced Level) Practice 散列题 目录 <算法笔记> 重点摘要 1002 A+B for Polynomials (25) 1009 Product ...

  7. PAT甲级 字符串处理题_C++题解

    字符串处理题 目录 <算法笔记> 重点摘要 1001 A+B Format (20) 1005 Spell It Right (20) 1108 Finding Average (20) ...

  8. PAT甲级 并查集 相关题_C++题解

    并查集 PAT (Advanced Level) Practice 并查集 相关题 <算法笔记> 重点摘要 1034 Head of a Gang (30) 1107 Social Clu ...

  9. PAT甲级 图的遍历 相关题_C++题解

    图的遍历 PAT (Advanced Level) Practice 图的遍历 相关题 目录 <算法笔记>重点摘要 1021 Deepest Root (25) 1076 Forwards ...

随机推荐

  1. Tkinter 之Grid布局

    一.参数说明 参数 作用 column  指定组件插入的列(0 表示第 1 列)默认值是 0 columnspan  指定用多少列(跨列)显示该组件 row  指定组件插入的行(0 表示第 1 行) ...

  2. Java 学习资料网站集合

    一.开源项目的搜集 https://www.jianshu.com/p/6c75174e0f07 -- https://github.com/flyleft/tip 二.简单的开源项目 https:/ ...

  3. LUA 在C函数中保存状态:registry、reference

    1 背景 lua的值一般都是保存在栈里面,调用函数完毕值在栈会被清掉,从而被GC回收.但有时候C函数需要在函数体的作用域之外保存某些Lua数据,这些数据不能存放在栈里面,有没有全局变量之类的可以存放. ...

  4. RK3399 4G模块移远EC20移植调试

    转载请注明出处:https://www.cnblogs.com/lialong1st/p/11266330.html CPU:RK3399 系统:Android 7.1 1.通过串口打印或者adb获取 ...

  5. Thingsboard学习之一CentOS安装系统更新

    首先安装好系统,查询到系统的IP地址后,使用Putty登入系统 更新系统 yum update 安装git yum install git 动图演示

  6. Fiddler is not capturing web request from Firefox

    Fiddler is not capturing web request from Firefox You can also get the FiddlerHook plug in for Firef ...

  7. 数据分析之 pandas

    pandas的拼接操作 pandas的拼接分为两种: 级联:pd.concat, pd.append 合并:pd.merge, pd.join 1. 使用pd.concat()级联 pandas使用p ...

  8. grub下如何指定哪个分区为根文件系统?

    答: 使用root命令,如: grub> set root=(hd0,msdos1)

  9. PHPStorm_CI3框架代码提示

    链接:https://pan.baidu.com/s/12lpkjRXod5yZINqcF6S6og  密码:t6if

  10. JavaScript箭头函数(Lambda表达式)

    箭头函数也叫lambda表达式 据说其主要意图是定义轻量级的内联回调函数 栗有: 1 var arr = ["wei","ze","yang" ...