二叉树结构
1.递归思想
大学时期对递归一直不是很清晰,其实大部分情况下能通循环最好就使用循环,因为递归不断调用函数会导致程序运行效率下降。递归的有点在简化思路,程序员只需要考虑当前步骤需要做什么,我的理解中递归的实现需要的是可重复的步骤以及递归的终止条件,在实际情况中,很多问题用循环实现会很难实现,简单的例子就是快速排序算法,使用递归思路很简单,而使用循环。。。那可能还需要一个栈的数据结构存放节点。
前几天看到的找零问题就可以使用递归的思路,轻松解决问题。
题目是这样的:
小易准备去魔法王国采购魔法神器,购买魔法神器需要使用魔法币,但是小易现在一枚魔法币都没有,但是小易有两台魔法机器可以通过投入x(x可以为0)个魔法币产生更多的魔法币。
魔法机器1:如果投入x个魔法币,魔法机器会将其变为2x+1个魔法币 魔法机器2:如果投入x个魔法币,魔法机器会将其变为2x+2个魔法币
小易采购魔法神器总共需要n个魔法币,所以小易只能通过两台魔法机器产生恰好n个魔法币,小易需要你帮他设计一个投入方案使他最后恰好拥有n个魔法币。
只看算法部分:
def Exchange(target):
if target==0:
return
elif target%2:
target=(target-1)/2
Exchange(target)
print(1)
else:
target=(target-2)/2
Exchange(target)
print(2)
只需要从最后一步开始,每一步向前推进一个步骤,函数只需要考虑当前步骤需要做的事情即可。
2.二叉树的定义
二叉树是一个连通的无环图,并且每一个顶点的度不大于3。有根二叉树还要满足根结点的度不大于2。有了根结点之后,每个顶点定义了唯一的父结点,和最多2个子结点。然而,没有足够的信息来区分左结点和右结点。如果不考虑连通性,允许图中有多个连通分量,这样的结构叫做森林。
二叉树的五种基本形态
1. 空二叉树
2. 只有一个根节点
3. 根节点只有左子树
4. 根节点只有右子树
5. 根节点既有左子树又有右子树
3.二叉树相关性质
1. 在二叉树第i层上最多有2^(i-1)个节点。
2. 深度为k的二叉树最多有2^k-1个节点
3. 对于任何一个二叉树T,如果其终端节点数为n0,度为二的根节点数为n2则n0=n2+1
4. 具有n个节点的完全二叉树的深度为\log 2_n +1
4.二叉树的遍历
前序遍历
总是先查找根节点,之后查找左子树,最后查找右子树。(根左右)
上图按照前序遍历应该为:ABDEC
中序遍历
总是先查找左子树,再查找根,最后查找右子树。(左根右)
上图按照中序遍历就应该为:DBEAC
后序遍历
总是先查找左子树,再查找右子树,最后查找根节点。(左右根)
上图按照后序遍历就应该为:DEBCA
出了前序遍历和后序遍历的组合外,任意两个遍历方法值都能确定一个二叉树。
5.建立二叉树
因为一种遍历方式的值并不能唯一确定一个二叉树,所以需要用两种遍历值来确定,当然还有一种更简单的方法,空出来的节点用一个特殊字符表示,这里选择用’#’来表示空的节点。上图进行变换后应该如下图所示。
此时如果采用前序遍历那么结果应该是:ABD##E##C##,此时该二叉树是唯一确定的。
采用前序遍历的结果作为生成二叉树的依据。
**构建时采用递归思路,每一个步骤都是写入根节点,开辟左节点内存,右节点内存,进入左节点,进入右节点。
终止条件是:当该节点的值为’#’时,写入根节点,不再开辟左右几点内存,返回**
C/C++实现如下:
//节点类
class TreeNode
{
public:
int date;
TreeNode*LeftChild;
TreeNode*RightChild;
};
二叉树类型:
class BiTree
{
public:
TreeNode*Root;
void CreateTree(TreeNode**ptr,int *s);
int Deepth(TreeNode*ptr);
BiTree(int*s);//构造函数 使用int数组来构造树
int GetDeepth();//获得二叉树的深度
};
这里为了后面的搜索二叉树,存放的不再是字符(char类型)而换成了(int类型),-1代表空,也就是说将’#’换成-1。
构造方法:
BiTree::BiTree(int*s)
{
Root = new TreeNode;
CreateTree(&Root,s);
}
void BiTree::CreateTree(TreeNode**ptr, int*s)
{
static int index = 0;
if (s[index] == -1)
{
(*ptr)->date = -1;
(*ptr)->LeftChild = NULL;
(*ptr)->RightChild = NULL;
index++;
}
else
{//根左右的前序遍历方法
(*ptr)->LeftChild = new TreeNode;
(*ptr)->RightChild = new TreeNode;
(*ptr)->date = s[index++];
CreateTree(&(*ptr)->LeftChild, s);
CreateTree(&(*ptr)->RightChild, s);
}
}
该构造函数需要输入的int数组是正确符合前序遍历的,否则可能出现数组越界问题。
获取二叉树深度
int BiTree::GetDeepth()
{
return Deepth(Root);
}
int BiTree::Deepth(TreeNode*ptr)
{
if (ptr->date == -1)
{
return 0;
}
int nLeft = Deepth(ptr->LeftChild);
int nRight = Deepth(ptr->RightChild);
return nLeft > nRight ? nLeft + 1 : nRight + 1;
}

本文探讨了递归思想的应用及二叉树的基本概念、性质与遍历方法,并介绍了二叉树的构建过程。
249

被折叠的 条评论
为什么被折叠?



