如果需要二叉树相关的比如二叉树的 二叉树迭代非迭代遍历 反向创建二叉树 创建查找二叉树 查找二叉树的查找和删除:可以参考我上传的代码
树:
树(Tree)是n(n>=0)个系欸但的有限集。n=0时成为空树。在任意一颗非空树中:
- 有切仅有一个特定的根(Root)的节点;
当n>1时,其余节点可分为m(m>0)个互不相交的有限集T1,T2……Tm,其中每个集合本身又是一棵树,并且成为根的子树(SubTree).
节点的度节点拥有的子树,称为节点的度。度为0的节点成为叶子节点或终端节点,度不为0的节点称为非终端节点或分支节点。除根节点以外,分支节点也称为内部节点。树的度是树内各节点的度的最大值。
层次与深度
节点的层次从根开始定义起,根为第一层。根的孩子为第二层。若某节点在第l层,则其子树的根就在第l+1层。其双亲在同一层的节点互为堂兄弟。有序树与无序树
如果将树中节点的各子树看成从左至右是有次序的。不能互换的,则称该树为有序树,否则为无序树。森林
森林是m(m>=0)棵互不相交的树的集合。
树的存储结构简单的顺序存储不能满足树的实现
结合顺序存储和链式存储来实现
三种表示方法
双亲表示法
- 孩子表示法
孩子兄弟表示法
双亲表示法
在每个节点中,附设一个指示器指示双亲节点到链表中的位置。
孩子表示法1
2
最终方案
孩子兄弟表示法
二插树
二叉树(Binary Tree)是(n>=0)个节点的有限集合,该集合或者为空集,(称为空二叉树),或者由一个根节点,和两棵互不相交的。分别称为根节点的左子树和右子树的二叉树组成。
特殊二叉树-斜树
所有的结点都只有左子树的二叉树叫左斜树。所有结点都是只有右子树的二叉树叫右斜树。这两者统称为斜树
线性表结构其实可以理解为树的一种树表达形式
满二叉树
在一棵二叉树中,如果所有的分支节点都存在左子树和右子树。并且所有叶子节点都在同一层上。这样的二叉树成为满二叉树。
完全二叉树
对一棵具有n个结点的二叉树按层次编号,如果编号为(1<=i<=n)的结点与同样深度的满二插树中编号为i的结点在二叉树中位置完全相同,则这棵二叉树成为完全二叉树。
二叉树的性质
- 性质1:在二叉树的第i层上至多有2i-1个结点(i>=1)。
- 性质2:深度为k的二叉树至多有2k-1个结点(k>=1)。
性质3:对任何一颗二叉树T,如果其终端结点数为n0,度为2的 结点 数为n2,则n0 = n2+1.
性质4:具有n个结点的完全二叉树深度为[log2n]+1 ([x]表示不 大于 x的最大整数)。
性质5:如果对一颗有n个结点的完全二叉树(其深度为[log2n]+1) 的结点按层序编号(从第1层到第[log2n]+1层,每层从左到 右),对任意一个结点i(1<=i<=n)有:
1).如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是结 点[i/2]
2).如果2i>n,则结点i无左孩子(结点i为叶子结点);否则其左孩 子是结点2i。
3).如果2i+1>n,则结点i无右孩子;否则其右孩子是结点2i+1。
二叉链表
二叉树的遍历
/**
* 前序遍历------迭代
*
* @param node
*/
public void preOrder(TreeNode node) {
if (node == null) {
return;
} else {
System.out.println(node.data);
preOrder(node.leftChild);
preOrder(node.rightChild);
}
}
/**
* 中序遍历------迭代
*
* @param node
*/
public void midOrder(TreeNode node) {
if (node == null) {
return;
} else {
midOrder(node.leftChild);
System.out.println(node.data);
midOrder(node.rightChild);
}
}
/**
* 后续遍历------迭代
*
* @param node
*/
public void postOrder(TreeNode node) {
if (node == null) {
return;
} else {
postOrder(node.leftChild);
postOrder(node.rightChild);
System.out.println(node.data);
}
}
/**
* 前序遍历------非迭代
*/
public void preOrderNoIterator(TreeNode node) {
if (node == null) {
return;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(node);
while (!stack.isEmpty()) {
// 出栈
TreeNode n = stack.pop();
System.out.println(n.getData());
// 入栈
if (n.rightChild != null) {
stack.push(n.rightChild);
}
if (n.leftChild != null) {
stack.push(n.leftChild);
}
}
/**
* 中序遍历------非迭代
*/
public void midOrderNoIterator(TreeNode node) {
if (node == null) {
return;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
while (node != null || !stack.isEmpty()) {
while (node != null) {
stack.push(node);
node = node.leftChild;
}
TreeNode popNode = stack.pop();
System.out.println(popNode.data);
node = popNode.rightChild;
}
}
/**
* 后序遍历===========非迭代
*/
private void postOrderNoIteraor(TreeNode node) {
if (node == null) {
return;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode popNode = null;
while (node != null || !stack.isEmpty()) {
// 3 如果右结点为空 弹出最左节点
if (node == null) {
popNode = stack.pop();
System.out.println(popNode.data);
}
// 1找到最左结点
while (node != null) {
stack.push(node);
node = node.leftChild;
}
//4如果peek的节点是刚pop出去的 要把此peek的节点pop
if (stack.peek() != null && stack.peek().rightChild != null
&& stack.peek().rightChild == popNode) {
TreeNode midNode = stack.pop();
System.out.println(midNode.data);
}
// 2 把最左结点的右结点重新循环的起点
if (!stack.isEmpty()) {
TreeNode msLeftNode = stack.peek();
node = msLeftNode.rightChild;
}
}
}