题目和STL实现:DS实验题 融合软泥怪-1

用堆实现优先队列

引言和堆的介绍摘自:Priority Queue(Heaps)--优先队列(堆)

引言:

优先队列是一个至少能够提供插入(Insert)和删除最小(DeleteMin)这两种操作的数据结构。对应于队列的操作,Insert相当于Enqueue,DeleteMin相当于Dequeue。

链表,二叉查找树,都可以提供插入(Insert)和删除最小(DeleteMin)这两种操作,但是为什么不用它们而引入了新的数据结构的。原因在于应用前两者需要较高的时间复杂度。对于链表的实现,插入需要O(1),删除最小需要遍历链表,故需要O(N)。对于二叉查找树,这两种操作都需要O(logN);而且随着不停的DeleteMin的操作,二叉查找树会变得非常不平衡;同时使用二叉查找树有些浪费,因此很多操作根本不需要。

因此这里引入一种新的数据结构,它能够使插入(Insert)和删除最小(DeleteMin)这两种操作的最坏时间复杂度为 O(N) ,而插入的平均时间复杂度为常数时间,即O(1)。同时不需要引入指针。

二叉堆

Heap有两个性质:结构性质(structure property),堆的顺序性(heap order property)。看英文应该比较好理解。

structure property

Heap(堆)是一个除了底层节点外的完全填满的二叉树,底层可以不完全,左到右填充节点。(a heap is a binary tree that completely filled, with the exception of bottom level, which is filled from left to right.)这样的树叫做完全二叉树。

一个高度为h 的完全二叉树应该有以下的性质:

a) 有2h到2h-1个节点

b) 完全二叉树的高度为logN

鉴于完全二叉树是一个很整齐的结构,因此可以不用指针而只用数组来表示一颗完全二叉树。 对于处于位置i 的元素,

a)他的左子节点在2i,右子节点在(2i+1)

b) 它的父节点在【i/2】(向下取整)

下图显示了完全二叉树与数组的对应关系:

实现

有了上面的基础之后,其实建堆和维护堆并不是一件难事,这里大概描述下我的思路。

1.我们使用数组模拟堆,i是当前节点,i/2是它的父亲节点,i2和i2+1或者i*2-1(如果存在的话)是它的左右儿子。

2.刚刚开始建堆的时候,从size到1遍历一遍,每一个节点向上进行维护,进行初始化。

3.维护的方法:比较当前节点和父亲节点 => 如果父亲节点的值大于当前节点的值,则进行交换,同时当前节点来到此时的父亲节点处,父亲节点找它的父亲节点 || 如果父亲节点的值小于当前节点的值,结束。

4.加入一个元素的方法:在堆尾,也就是Heap[size+1],插入新的节点 => size++ => 步骤3。

5.删除最小节点的方法:将最后一个节点和最小的节点交换 => 删除最后一个节点 => 执行步骤2。

代码

//
// main.cpp
// Heap
//
// Created by wasdns on 16/12/25.
// Copyright © 2016年 wasdns. All rights reserved.
// #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; int size = 0; int Heap[100005]; /*
维护函数keep
*/
void keep(int son)
{
int fa = son/2; while (fa >= 1 && Heap[fa] > Heap[son])
{
int t = Heap[fa];
Heap[fa] = Heap[son];
Heap[son] = t; son = fa;
fa = fa/2;
}
} /*
初始化函数IniHeap
*/
void IniHeap()
{
int i; for (i = size; i >= 1; i--)
{
keep(i);
}
} /*
InsProtect函数:插入新节点并维护
*/
void InsProtect(int a)
{
Heap[++size] = a; keep(size);
} /*
DelMin函数:删除最小元并维护
*/
int DelMin()
{
int minum = Heap[1]; int t = Heap[size]; Heap[1] = t; size--; IniHeap(); return minum;
} int main()
{
cin >> size; for (int i = 1; i <= size; i++)
{
cin >> Heap[i];
} IniHeap(); int cnt = 0; while (size != 1)
{
int a = DelMin();
int b = DelMin(); cnt += a+b; InsProtect(a+b);
} cout << cnt << endl; return 0;
} /*
14
4 3 2 6 7 1 3 5 4 3 8 2 1 7
*/

2016/12/25

DS实验题 融合软泥怪-2 Heap实现的更多相关文章

  1. DS实验题 融合软泥怪-1

    题目 思路 很容易想到第一种做法,用Huffman算法,从森林中找出两个值最小的节点,合并再加入森林,在这个过程中不断记录. 但是每一次需要sort一遍,将最小的两个值节点置于头两个节点,最坏情况下复 ...

  2. DS实验题 Old_Driver UnionFindSet结构 指针实现邻接表存储

    题目见前文:DS实验题 Old_Driver UnionFindSet结构 这里使用邻接表存储敌人之间的关系,邻接表用指针实现: // // main.cpp // Old_Driver3 // // ...

  3. DS实验题 Dijkstra算法

    参考:Dijkstra算法 数据结构来到了图论这一章节,网络中的路由算法基本都和图论相关.于是在拿到DS的实验题的时候,决定看下久负盛名的Dijkstra算法. Dijkstra的经典应用是开放最短路 ...

  4. DS实验题 sights

    算法与数据结构实验题 6.3 sights ★实验任务 美丽的小风姑娘打算去旅游散心,她走进了一座山,发现这座山有 n 个景点, 由于山路难修,所以施工队只修了最少条的路,来保证 n 个景点联通,娇弱 ...

  5. DS实验题 order

    算法与数据结构 实验题 6.4 order ★实验任务 给出一棵二叉树的中序遍历和每个节点的父节点,求这棵二叉树的先序和后序遍历. ★数据输入 输入第一行为一个正整数n表示二叉树的节点数目,节点编号从 ...

  6. DS实验题 Order 已知父节点和中序遍历求前、后序

    题目: 思路: 这题是比较典型的树的遍历问题,思路就是将中序遍历作为位置的判断依据,假设有个节点A和它的父亲Afa,那么如果A和Afa的顺序在中序遍历中是先A后Afa,则A是Afa的左儿子,否则是右儿 ...

  7. DS实验题 Inversion

    题目: 解题过程: 第一次做这题的时候,很自然的想到了冒泡和选择,我交的代码是用选择写的.基本全WA(摊手). 贴上第一次的代码: // // main.cpp // sequenceschange ...

  8. DS实验题 Missile

    题目: 提示:并没有精度问题. 原题 NOIP2010 导弹拦截 思路 设源点为A(x1, y1)和B(x2, y2). 第一步,用结构体存节点,包括以下元素: 1.横坐标x 2.纵坐标y 3.节点和 ...

  9. DS实验题 击鼓传花

    题目: 代码1(数组实现): // // main.cpp // DS-击鼓传花 // // Created by wasdns on 16/11/9. // Copyright © 2016年 wa ...

随机推荐

  1. IOS单元测试,OCMock

    1.环境搭建 使用官方推荐,手动搭建.. 1.下载所需文件 http://ocmock.org/download/ 根据自己的需要下载不同的版本. 打开iOS library文件夹,里面就有需要用到的 ...

  2. python3 黑板客爬虫闯关游戏(二)

    第二关猜登录密码,需要用到urllib.request和urllib.parse 也很简单,给代码 import urllib.request as ur import urllib.parse as ...

  3. ACM-ICPC代码模板

    是不是感觉手中的模板都各有缺陷? 要找到好的模板就要集百家之所长, 我在这里贡献出我的代码模板丰富大家的积累. 我的模板能较好的与常见的模板形成互补. 赶快收藏吧,否则以后找不到就不好啦! 另外,想成 ...

  4. Redis 复制、Sentinel的搭建和原理说明

    背景: Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端) ...

  5. 【Objective-C】NSDate详解及获取当前时间等常用操作

    NSDate类用于保存时间值,同时提供了一些方法来处理一些基于秒级别时差(Time Interval)运算和日期之间的早晚比较等. 1. 创建或初始化可用以下方法 用于创建NSDate实例的类方法有 ...

  6. button按钮波纹,箭头特效css

    波纹特效: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <tit ...

  7. 如何在 SSAS服务器之间做同步

    简介: 从SQL Server 2005开始,分析服务就支持了同步的功能.本文将介绍如何在SQL Server 2012下同步Adventureworks的分析服务数据库.通过同步的功能,我们就来可以 ...

  8. 【康拓展开】及其在求全排列第k个数中的应用

    题目:给出n个互不相同的字符, 并给定它们的相对大小顺序,这样n个字符的所有排列也会有一个顺序. 现在任给一个排列,求出在它后面的第i个排列.这是一个典型的康拓展开应用,首先我们先阐述一下什么是康拓展 ...

  9. ADO.NET 读取Excel文件,并作数据源

    项目中需要用的功能,贴上代码了. 需要注意的地方:配置Web.config的时候要注意版本问题! //若是在Web.config中配置数据源,如下 <add key="ExcelCon ...

  10. 常见开发需求之js处理url汉字编码中的乱码

    需求及解决    两个页面传值的需求是很常见的,angular中有很多常见的方法用于传值,而且都不会受到字符编码的影响,而采用传统的url中拼字符串进行传值的操作,如果拼串中涉及到中文字符,我们就要考 ...