图的深搜与广搜

复习下二叉树、图的深搜与广搜。

从图的遍历说起。图的遍历方法有两种:深度优先遍历(Depth First Search), 广度优先遍历(Breadth First Search),其经典应用走迷宫、N皇后、二叉树遍历等。遍历即按某种顺序訪问“图”中全部的节点,顺序分为:

  • 深度优先(优先往深处走),用的数据结构是栈, 主要是递归实现。
  • 广度优先(优先走近期的)。用的数据结构是队列。主要是迭代实现。

对于深搜。因为递归往往能够方便的利用系统栈,不须要自己维护栈。所以通常实现比較简单。

而对于广搜。则须要自己维护一个队列,且因为队列大小未知,底层存储的物理结构採用链式存储。

二叉树概念和性质

二叉树是每个节点最多有两个子树的树结构,常被用于实现二叉查找树和二叉堆。

在图论中,二叉树定义是一个连通的无环图。而且每个顶点的度不大于2。二叉树和树有非常多类似之处,但并非树的特殊情形,主要有下面三点主要区别:

  1. 树中结点的最大度数没有限制,而二叉树结点的最大度数为2。
  2. 树的结点无左、右之分,而二叉树的结点有左、右之分;
  3. 树的结点个数至少为1,而二叉树的结点个数能够为0

树的一些相关概念:

  • 结点的度:结点所拥有的子树的个数称为该结点的度。二叉树就仅仅有 0,1。2 三种情况;
  • 叶结点:度为 0 的结点称为叶结点,或者称为终端结点;
  • 分枝结点:度不为 0 的结点称为分支结点,一棵树的结点除叶结点外,其余的都是分支结点。
  • 结点的层数: 规定树的根结点的层数为 1,其余结点的层数等于它的双亲结点的层数加 1;
  • 树的深度: 树中全部结点的最大层数称为树的深度;
  • 路径、路径长度。假设一棵树的一串结点 n(1), n(2),  …, n(k)  有例如以下关系:结点 n(i) 是 n(i+1) 的父结点 (1≤i<k), 就把 n(1),n(2),…,n(k) 称为一条由 n(1) 至 n(k) 的路径。

    这条路径的长度是 k-1;

  • 满二叉树: 在一棵二叉树中,假设全部分支结点都存在左子树和右子树,而且全部叶子结点都在同一层上。
  • 全然二叉树: 深度为 K 的。有 N 个结点的二叉树,当且仅当其每个结点都与深度为 K 的满二叉树中按层序编号从 1 至 N 的结点一一相应;
  • 堆是一种全然二叉树,经常使用的排序算法、Dijkstra 算法、Prim 算法等都经常使用堆优化;
  • AVL树:它是最先发明的自平衡二叉查找树, 名字来源于其发明者,AVL 树中不论什么节点的两个子树的高度最大区别为 1, 查找、插入和删除在平均和最坏情况下都是 O(logn);

二叉树的重要的性质:

  • 性质1:在二叉树的第 i 层上至多有 2i-1 个结点 (i≥1);
  • 性质2:深度为 k 的二叉树上至多含 2k-1 个结点 (k≥1);
  • 性质3:对不论什么一棵二叉树,若它含有 n0 个叶子结点、n2 个度为 2 的结点,则:n0 = n2+1;
  • 性质4:具有 n 个结点的全然二叉树的深度为 log2n+1;
  • 性质5:若对含 n 个结点的全然二叉树从上到下且从左至右(即按层序)进行 1 至 n 的编号。则对全然二叉树中随意一个编号为 i 的结点:
    (1) 若 i=1,则该结点是二叉树的根,无双亲,否则。编号为 i/2  的结点为其双亲结点;
    (2) 若 2i>n。则该结点无左孩子。否则,编号为 2i 的结点为其左孩子结点。
    (3) 若 2i+1>n,则该结点无右孩子结点。否则,编号为 2i+1 的结点为其右孩子结点;

小实验(C 实现)

这里首先用一个数组生成一个全然二叉树(链式存储), 然后深搜用前序遍历,广搜借助自己实现的一个队列(链式存储)来进行。图例如以下所看到的:

代码为:

#include <stdio.h>
#include <stdlib.h> typedef struct Node {
int data;
struct Node * left;
struct Node * right;
} BitNode, *BiTree; typedef BiTree QElemType; // 定义队列元素类型 typedef struct QNode {
QElemType data; // 存放树节点指针
struct QNode *next;
} QNode, *QueuePtr; // 队列节点和节点指针 typedef struct LinkQueue {
QueuePtr front, rear;
} LinkQueue; // 队列前后指针: 队首。队尾 /* 初始化队列 */
int InitQueue(LinkQueue *Q) {
QueuePtr s = (QueuePtr) malloc(sizeof(QNode));
if (!s) return 0;
Q->front = s;
Q->rear = s;
return 1;
} /* 入队 */
int EnQueue(LinkQueue *Q, QElemType e) {
if (e == NULL) return 0;
QueuePtr s = (QueuePtr) malloc(sizeof(QNode));
if (!s) return 0;
s->data = e;
s->next = NULL;
Q->rear->next = s;
Q->rear = s;
return 1;
} /* 出队 */
int DeQueue(LinkQueue *Q, QElemType *e) {
if (Q->front == Q->rear) {
return 0;
} // 首位指针相等。队列空,出队失败
QueuePtr p;
p = Q->front->next; // 头结点不放数据,其后继结点作为队首,出队
*e = p->data;
Q->front->next = p->next; // 队首指针后移一个节点
if (Q->rear == p) {
Q->rear = Q->front;
} // 尾指针假设指向的是头结点后第一个节点,则令其指向队首指针。 即队列仅仅有一个数据节点的情况
free(p);
return 1;
} /* 利用数组 a 创建二叉树。递归的编写技巧在于设计好函数接口 */
void CreateTree(BiTree *bt, int a[], int len, int index) {
if (index > len - 1)
return;
(*bt) = (BiTree) malloc(sizeof(BitNode)); // 指针变量初始化堆区的内存,c 用 malloc 函数
(*bt)->data = a[index];
(*bt)->left = NULL; // 不能能省略,当其为叶节点时,指针域为 NULL,而且常作为程序推断条件
(*bt)->right = NULL;
CreateTree(&((*bt)->left), a, len, 2 * index + 1);
CreateTree(&((*bt)->right), a, len, 2 * index + 2);
} /* 前序遍历二叉树 , 属于深度优先遍历 DFS */
void PreOrderTraverse(BiTree bt) {
if (bt == NULL)
return;
printf("%d ", bt->data); // 操作节点数据
PreOrderTraverse(bt->left);
PreOrderTraverse(bt->right);
} /* 按层遍历,即广度优先遍历 BFS */
void BFSTraverse(BiTree bt) {
LinkQueue *Q = (LinkQueue *) malloc(sizeof(LinkQueue));
BiTree e;
InitQueue(Q);
EnQueue(Q, bt);
while (Q->front != Q->rear) {
DeQueue(Q, &e);
printf("%d ", e->data);
EnQueue(Q, e->left);
EnQueue(Q, e->right);
}
} int main() {
int arr[] = { 0, 1, 2, 3, 4, 5, 6};
BiTree root;
CreateTree(&root, arr, sizeof(arr) / sizeof(int), 0);
printf("PreOrderTraverse: ");
PreOrderTraverse(root);
printf("\nBFSOrderTravesre: ");
BFSTraverse(root);
return 0;
} /*
程序执行例如以下:
PreOrderTraverse: 0 1 3 4 2 5 6
BFSOrderTravesre: 0 1 2 3 4 5 6
*/

【文章地址为:http://blog.csdn.net/thisinnocence】

算法学习笔记(六) 二叉树和图遍历—深搜 DFS 与广搜 BFS的更多相关文章

  1. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  2. # go微服务框架kratos学习笔记六(kratos 服务发现 discovery)

    目录 go微服务框架kratos学习笔记六(kratos 服务发现 discovery) http api register 服务注册 fetch 获取实例 fetchs 批量获取实例 polls 批 ...

  3. 学习笔记:APP切图那点事儿–详细介绍android和ios平台

    学习笔记:APP切图那点事儿–详细介绍android和ios平台 转载自:http://www.woofeng.cn/articles/168.html   版权归原作者所有 作者:亚茹有李 原文地址 ...

  4. 【opencv学习笔记六】图像的ROI区域选择与复制

    图像的数据量还是比较大的,对整张图片进行处理会影响我们的处理效率,因此常常只对图像中我们需要的部分进行处理,也就是感兴趣区域ROI.今天我们来看一下如何设置图像的感兴趣区域ROI.以及对ROI区域图像 ...

  5. Johnson算法学习笔记

    \(Johnson\)算法学习笔记. 在最短路的学习中,我们曾学习了三种最短路的算法,\(Bellman-Ford\)算法及其队列优化\(SPFA\)算法,\(Dijkstra\)算法.这些算法可以快 ...

  6. 某科学的PID算法学习笔记

    最近,在某社团的要求下,自学了PID算法.学完后,深切地感受到PID算法之强大.PID算法应用广泛,比如加热器.平衡车.无人机等等,是自动控制理论中比较容易理解但十分重要的算法. 下面是博主学习过程中 ...

  7. Java IO学习笔记六:NIO到多路复用

    作者:Grey 原文地址:Java IO学习笔记六:NIO到多路复用 虽然NIO性能上比BIO要好,参考:Java IO学习笔记五:BIO到NIO 但是NIO也有问题,NIO服务端的示例代码中往往会包 ...

  8. Johnson 全源最短路径算法学习笔记

    Johnson 全源最短路径算法学习笔记 如果你希望得到带互动的极简文字体验,请点这里 我们来学习johnson Johnson 算法是一种在边加权有向图中找到所有顶点对之间最短路径的方法.它允许一些 ...

  9. C / C++算法学习笔记(8)-SHELL排序

    原始地址:C / C++算法学习笔记(8)-SHELL排序 基本思想 先取一个小于n的整数d1作为第一个增量(gap),把文件的全部记录分成d1个组.所有距离为dl的倍数的记录放在同一个组中.先在各组 ...

随机推荐

  1. hdoj-1016-Prime Ring Problem【深搜】

    Prime Ring Problem Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...

  2. php将数组或字符串写入文件

    //将数组保存在文件里 function export_to_file($file, $variable) { $fopen = fopen($file, 'wb'); if (!$fopen) { ...

  3. Qt源码编译

    Qt源码编译 eryar@163.com Key words. Qt, 源码编译 1.Introduction 随着Qt版本升级,源码编译出来的库体积越来越大.如果只是用Qt来做GUI,Qt提供的预编 ...

  4. js---16继承

    123 instanceof Number;//false,要左边是对象右边是函数 typeof 123 ; //number new Number(123) instanceof Number; / ...

  5. js---04 属性 this

    var oUl = document.getElementsByTagName('ul')[0]; var aLi = oUl.getElementsByTagName('li'); window.o ...

  6. Linux集群的I/O性能测试

    Linux集群的I/O性能测试   本文介绍利用iozone的性能测试工具,来测试集群性能.测试步骤如下:1.在Server节点上安装iozone(可以到www.iozone.org上下载) #rpm ...

  7. mvc4 视图中的form如何获取

    public ActionResult Index(FormCollection form)         {             var Name = form["字段名" ...

  8. API集合开发文档

    百度翻译api https://www.cnblogs.com/DevilX5/p/7079470.html 实现QQ第三方登录.网站接入 http://blog.csdn.net/u01067894 ...

  9. postgresql sql语句 更改表名

    SELECT'alter table "public"."'|| t.tablename||'"'||' rename to "'|| "l ...

  10. vue2.0 transition用法

    html: <div id="demo"> <button v-on:click="show = !show"> Toggle < ...