《啊哈算法》第七章 神奇的树
2016-05-15 11:03
239 查看
参考:《啊哈算法》
连通是说其其中任意两点之间是可达的
不包含回路就是说一定能够不会出现走一圈的情况
**
一棵树如果有n个结点,那么它一定恰好有n-1条边
在一棵树中加一条边将会构成回路
为了确定一棵树的形态,在树中可以指定一个特殊的结点—–根
如果一个结点没有子结点,这个结点就称为叶结点。
没有父结点的结点称为根结点。
如果一个结点既不是根结点也不是叶结点,则称为内部结点。
每个结点还有深度,深度是指从根结点到这个结点的层数(根为第一层)
所有的叶结点都有相同的深度
完全二叉树
如果一棵二叉树除了最右边位置上有一个或者几个叶结点缺少外,其他事丰满的二叉树,就是满二叉树。
(完全二叉树的典型应用就是堆)
所有的父结点都比子结点要大的完全二叉树称为最大堆(大顶堆)
当然还可以通过建立大顶堆的方式进行堆排序。
虽然这里的堆排序看上去很是费时,但是要是使用在添加一个数,或者添加一个数同时删除一个数的情况时就比较的高效了。比如我们删除一组数的最小值,并新增一个数,同时求新数组的最小值时。直接将新增的数放到小顶堆的堆顶(本身这里之前是最小的数),然后调整到符合小顶堆时的堆顶就是新的最小值。
另外要是我们新增一个数,但是不进行任何删除操作,只是最快求出新的最小值时,只需要将新增的数添加到最后。然后一路向上调整至符合要求,新的堆顶就是新的最小值。
堆还经常被用作求一个数列中第k大的数,只需要建立一个大小为k的小顶堆,堆顶就是第k大的数
树
树其实就是不包含回路的连通无向图
**连通是说其其中任意两点之间是可达的
不包含回路就是说一定能够不会出现走一圈的情况
**
树的特性
一棵树中的任意两个结点有且仅有唯一的一条路径连通一棵树如果有n个结点,那么它一定恰好有n-1条边
在一棵树中加一条边将会构成回路
为了确定一棵树的形态,在树中可以指定一个特殊的结点—–根
如果一个结点没有子结点,这个结点就称为叶结点。
没有父结点的结点称为根结点。
如果一个结点既不是根结点也不是叶结点,则称为内部结点。
每个结点还有深度,深度是指从根结点到这个结点的层数(根为第一层)
二叉树
严格递归定义:二叉树要么为空,要么由根结点、左子树和右子树组成,而左子树和右子树分别是一棵二叉树
二叉树中还有两种特殊的二叉树:
满二叉树所有的叶结点都有相同的深度
完全二叉树
如果一棵二叉树除了最右边位置上有一个或者几个叶结点缺少外,其他事丰满的二叉树,就是满二叉树。
(完全二叉树的典型应用就是堆)
堆—神奇的优先队列
所有的父结点都比子结点要小的完全二叉树称为最小堆(小顶堆)所有的父结点都比子结点要大的完全二叉树称为最大堆(大顶堆)
完全二叉树一个性质:最后一个非叶结点是第n/2个结点
建堆及堆排序的展示(小顶堆)
算法分析:先输入数据存在数组中建立一棵完全二叉树,然后从最后一个非叶结点一次向前进行调整。调整结束后就满足小顶堆,根结点就是最小值,此时记录下根结点,并将其从堆中删除,将最后一个结点送到根结点的位置,此时不满足小顶堆,我们就向下调整使其再次满足。重复步骤至完全二叉树为空#include <iostream> #include <cstdio> using namespace std; //向下调整 int h[102]; int n; void siftdown(int i) { int t,flag; while(i*2<=n&&flag==0) { if(h[i]>h[i*2]) {//先于左结点比 t=i*2; } else { t=i; } if(i*2+1<=n) {//是否有右结点 if(h[t]>h[i*2+1]) { t=i*2+1; } } if(t!=i) { swap(h[i],h[t]);//交换 i=t; } else { flag=1;//满足顶堆条件的信号传出 } } } //建堆 void create() { //从最后一个非叶结点到第一个结点依次进行向下调整 for(int i=n/2; i>=1; i--) { siftdown(i); } } //删除最大元素 int deletemax() { int t; t=h[1];//用临时变量记录堆顶点的值 h[1]=h ;//将堆的最后一个顶点赋值到堆顶 n--;//堆元素少一 siftdown(1);//向下调整 return t;//返回记录的堆的顶点的最小值 } int main() { int num; scanf("%d",&num); for(int i=1; i<=num; i++) { scanf("%d",&h[i]); } n=num; create(); for(int i=1; i<=num; i++) { printf("%d ",deletemax()); } return 0; }
测试样例
14 99 5 36 7 22 17 46 12 2 19 25 28 1 92
当然还可以通过建立大顶堆的方式进行堆排序。
虽然这里的堆排序看上去很是费时,但是要是使用在添加一个数,或者添加一个数同时删除一个数的情况时就比较的高效了。比如我们删除一组数的最小值,并新增一个数,同时求新数组的最小值时。直接将新增的数放到小顶堆的堆顶(本身这里之前是最小的数),然后调整到符合小顶堆时的堆顶就是新的最小值。
另外要是我们新增一个数,但是不进行任何删除操作,只是最快求出新的最小值时,只需要将新增的数添加到最后。然后一路向上调整至符合要求,新的堆顶就是新的最小值。
堆还经常被用作求一个数列中第k大的数,只需要建立一个大小为k的小顶堆,堆顶就是第k大的数
相关文章推荐
- Java基础 封装
- 加拿大滑铁卢大学Maluuba机器人的中文名称该如何翻译?
- 树链剖分求LCA(最近公共祖先)
- android开发笔记之sh脚本
- PHPCMS V9后台密码忘记重置工具
- mysql_command_study
- 【iOS】SDWebImage的图片缓存机制
- android 比较靠谱的图片压缩
- 在ios 7下,使用@import代替#import
- jquery.form&jersey异步上传图片(SpringMVC版本)
- 周易六十四卦——无妄卦
- 新增crawlingtosea.loaders.LoaderBitmapqueue包
- Context.getExternalFilesDir()和Context.getExternalCacheDir()
- android开发笔记之多媒体—MediaPlayer + SurfaceView播放视频
- Week,Month, Year 日期区间辅助类
- XenAPP6.5安装于部署(二)---安装XenAPP
- python函数定义
- Spinner的使用案例
- spring mvc 任务定时器 @Scheduled
- iOS开源库源码解析之SDWebImage