数据结构(三):非线性逻辑结构-二叉树

接着上一次对非线性逻辑数据结构树的内容,开启对二叉树的深入复习和总结。首先还是先回顾一下几个重要的概念:

一、回顾

1. 满二叉树与完全二叉树

满二叉树指的是除了叶子节点外所有的节点都有两个子节点。这样可以很容易的计算出满二叉树的深度,要掌握满二叉树的一些性质。

完全二叉树则是从满二叉树继承而来,指的所有的节点按照从上到下,从左到右的层次顺序依次排列所构成的二叉树称之为完全二叉树。所以可以想象,对于深度为h的完全二叉树,前h-1层可以构成深度为h-1的满二叉树,而对于第h层则是从左到右连续排列的。后面讲到的二叉树的存储结构当采用顺序结构时,为了能够记录二叉树节点有一个前驱和两个后继节点,以及方便插入等采用了完全二叉树的结构,将没有的节点当作虚节点,构建满二叉树,然后从上到下,从左到右依次存入即可。所以,了解满二叉树的性能是非常重要的。当然对于二叉树的存储,采用链式结构会更加的合适,后面会单独介绍。

有了这个性质,对于节点数为553的完全二叉树,可以很容易的计算出它的深度与每一层的节点数:

553 = (512-1)+ 42,所以它的深度为10,而第10层的节点数为42个,而前9层的二叉树结构构成深度为9的满二叉树。

2. 二叉树的存储

前面已经讲过了二叉树的顺序存储结构,是按照完全二叉树的结构进行的编排。这里讲解链式存储结构。

用链式存储结构存储二叉树是很自然的,节点除了数据域之外,设置了left和right两个指针域,分别存放该节点的左右孩子的地址。二叉树的链式存储结构成为二叉链表。其中root是指向根的指针,空树时root为NULL。

二叉树的二叉链表存储结构:

typedef struct tnode

{

DataType data;

struct tnode * left, * right;

}TNode;

当左孩子结点没有时,left = NULL,同理,当右孩子结点没有时,right = NULL。所以从插入、删除以及查找等各种角度上来讲,使用链式存储结构都比使用顺序存储结构要好很多。所以,以后对于二叉树的顺序存储结构只具有对比意义,在实际中都是采用链式存储结构。

二、二叉树的遍历

顺着某一条搜索路径巡访二叉树中的结点,使得每个结点均被访问一次,而且仅被访问一次,得到树中所有结点的一个线性排列,将树的结点线性化(定义一个次序)。“访问”的含义可以很广,如:输出结点的信息等。遍历是算法的基础,在线性结构中,遍历的顺序与逻辑顺序一样,所以遍历没有单独研究,而非线性遍历则复杂的多,方法也不止一种,而且算法直接与某种遍历相关联,因此把算法设计与遍历联系在一起研究。

层次遍历:从上到下、从左到右访问各结点;其示意图如下:

先序(前序)遍历:先访问根结点,然后分别先序遍历左子树、右子树;

中序遍历:先中序遍历左子树,然后访问根结点,最后中序遍历右子树;

后序遍历:先后序遍历左、右子树,然后访问根结点。

对于下图所示的简单的二叉树,采用不同的遍历方法,得到线性排列分别为:

层次遍历序列:A  B  C  D

先序遍历序列:A  B  D  C

中序遍历序列:B  D  A  C

后序遍历序列:D  B  C  A

三、二叉树的遍历算法

1. 递归算法

那么对于先序遍历的递归算法如下:

<span style="font-family:SimSun;font-size:18px;"><span style="font-size:18px;">void PreOrder(CNode *pNode)
{
	if(pNode!=NULL)
		{
			printf("%lf\t",pNode->data);
			PreOrder(p->lchild);
			PreOrder(p->rchild);
		}
}</span></span>

那么对于中序遍历的递归算法如下:

<span style="font-family:SimSun;font-size:18px;"><span style="font-size:18px;">void PreOrder(CNode *pNode)
{
	if(pNode!=NULL)
		{
			PreOrder(p->lchild);
                        printf("%lf\t",pNode->data);
			PreOrder(p->rchild);
		}
}</span></span>

类似的,对于后续遍历的递归算法如下:

<span style="font-family:SimSun;font-size:18px;"><span style="font-size:18px;">void PreOrder(CNode *pNode)
{
	if(pNode!=NULL)
		{
		        PreOrder(p->lchild);
			PreOrder(p->rchild);
                        printf("%lf\t",pNode->data);
		}
}</span></span>

2. 递归算法的评估

递归函数结构清晰,代码简洁,隐蔽了复杂的细节,而且许多算法由于本身就是递归定义的,所以用递归实现更加直接更方便,但是递归函数有以下不足:

(1) 执行效率低;

(2) 一次递归调用可能产生一层接一层的递归,连续地压栈也许会超出可用堆栈空间的范围;

(3) 递归函数的参数表特殊,通常要比非递归函数所需的参数要多;

(4) 递归设计不是面向对象的方法;

(5) 有些语言不允许使用递归调用。

当强调算法设计,运行时对时间和空间的要求合理,就可以使用递归。

对于使用递归和迭代这两种实现循环的方式,可以参考我的另一篇博文《迭代是人,递归是神(迭代与递归的总结:比较)》,里面有对迭代和递归详细的分析与对比。

***********************************************************************************************************************************************************************

2015-8-2

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-22 12:55:55

数据结构(三):非线性逻辑结构-二叉树的相关文章

数据结构(三):非线性逻辑结构-特殊的二叉树结构:堆、哈夫曼树、二叉搜索树、平衡二叉搜索树、红黑树、线索二叉树

在上一篇数据结构的博文<数据结构(三):非线性逻辑结构-二叉树>中已经对二叉树的概念.遍历等基本的概念和操作进行了介绍.本篇博文主要介绍几个特殊的二叉树,堆.哈夫曼树.二叉搜索树.平衡二叉搜索树.红黑树.线索二叉树,它们在解决实际问题中有着非常重要的应用.本文主要从概念和一些基本操作上进行分类和总结. 一.概念总揽 (1) 堆 堆(heap order)是一种特殊的表,如果将它看做是一颗完全二叉树的层次序列,那么它具有如下的性质:每个节点的值都不大于其孩子的值,或每个节点的值都不小于其孩子的值

数据结构 《22》---- 二叉树三种遍历的迭代器算法

二叉树的三种遍历有递归版本,和迭代版本.本文介绍一种新的思路. 参考了 http://coolshell.cn/articles/9886.html 在许多应用中,我们还需要对遍历本身进行抽象.假如有一个求和的函数sum,我们希望它能应用于链表,数组,二叉树等等不同的数据结构.这时,我们可以抽象出迭代器(Iterator)的概念,通过迭代器把算法和数据结构解耦了,使得通用算法能应用于不同类型的数据结构. 以下给出了三种遍历的迭代器算法. class Iterator { public: virt

数据结构与算法(二叉树)

二叉树的存储结构 二叉树的存储可分为两种:顺序存储结构和链式存储结构. 1.      顺序存储结构 把一个满二叉树自上而下.从左到右顺序编号,依次存放在数组内,可得到图6.8(a)所示的结果.设满二叉树结点在数组中的索引号为i,那么有如下性质. (1) 如果i = 0,此结点为根结点,无双亲. (2) 如果i > 0,则其双亲结点为(i -1) / 2 .(注意,这里的除法是整除,结果中的小数部分会被舍弃.) (3) 结点i的左孩子为2i + 1,右孩子为2i + 2. (4) 如果i >

javascript实现数据结构: 树和二叉树,二叉树的遍历和基本操作

树型结构是一类非常重要的非线性结构.直观地,树型结构是以分支关系定义的层次结构. 树在计算机领域中也有着广泛的应用,例如在编译程序中,用树来表示源程序的语法结构:在数据库系统中,可用树来组织信息:在分析算法的行为时,可用树来描述其执行过程等等. 下面讲解的内容完整代码在这:https://github.com/LukeLin/data-structure-with-js/blob/master/Binary%20tree/BinaryTree.js 首先看看树的一些概念: 1.树(Tree)是n

6. 蛤蟆的数据结构进阶六之二叉树排序树

6. 蛤蟆的数据结构进阶六之二叉树排序树 本篇名言:"有些人因为贪婪,想得更多的东西,却把现在所有的也失掉了. -- 伊索" 关于理论知识已经在上篇中进行描述,这篇我们主要来看下如何是实现二叉排序树. 欢迎转载,转载请标明出处: 1.  二叉排序树的定义 二叉排序树(BinarySort Tree)又称二叉查找(搜索)树(Binary Search Tree).其定义为:二叉排序树或者是空树,或者是满足如下性质的二叉树: ①若它的左子树非空,则左子树上所有结点的值均小于根结点的值: ②

数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树

[本文谢绝转载,原文来自http://990487026.blog.51cto.com] 树 数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树 二叉树的创建,关系建立 二叉树的创建,关系建立2 三叉链表法 双亲链表: 二叉树的遍历 遍历的分析PPT 计算二叉树中叶子节点的数目:使用全局变量计数器 计算二叉树中叶子节点的数目:不使用全局变量计数器 无论是先序遍历,中序遍历,后序遍历,求叶子的数字都不变;因为本质都是一样的,任何一个节点都会遍历3趟 求二叉树的高度 二叉树的拷

1、数据结构的基本逻辑结构、存储结构和运算

数据结构的基本逻辑结构.存储结构和运算 1.基本逻辑结构 集合结构.线性结构.树形结构和图状结构 2.基本存储结构 线性存储:需要一块连续的内存地址空间,相关元素一次存储 链接存储:不需要连续的地址空间,每个节点包含元素和链接两个部分,元素存储数据值,链接存储下一个节点的地址 3.基本运算 ·创建运算 ·清除运算 ·插入运算 ·搜索运算(根据值返回位置) ·更新运算 ·访问运算(根据位置返回值) ·遍历运算 1.数据结构的基本逻辑结构.存储结构和运算,布布扣,bubuko.com

数据结构实验之求二叉树后序遍历和层次遍历

数据结构实验之求二叉树后序遍历和层次遍历 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 已知一棵二叉树的前序遍历和中序遍历,求二叉树的后序遍历. 输入 输入数据有多组,第一行是一个整数t (t<1000),代表有t组测试数据.每组包括两个长度小于50 的字符串,第一个字符串表示二叉树的先序遍历序列,第二个字符串表示二叉树的中序遍历序列. 输出 每组第一行输出二叉树的后序遍历序列,第二行输出二叉树的层次遍历序列 示例输入 2

javascript实现数据结构: 树和二叉树的应用--最优二叉树(赫夫曼树),回溯法与树的遍历--求集合幂集及八皇后问题

赫夫曼树及其应用 赫夫曼(Huffman)树又称最优树,是一类带权路径长度最短的树,有着广泛的应用. 最优二叉树(Huffman树) 1 基本概念 ① 结点路径:从树中一个结点到另一个结点的之间的分支构成这两个结点之间的路径. ② 路径长度:结点路径上的分支数目称为路径长度. ③ 树的路径长度:从树根到每一个结点的路径长度之和. 以下图为例: A到F :结点路径 AEF : 路径长度(即边的数目) 2 : 树的路径长度:3*1+5*2+2*3=19: ④ 结点的带权路径长度:从该结点的到树的根结