您的位置:首页 > 编程语言

二叉树的各种概念以及代码操作

2017-03-18 12:26 501 查看

二叉树的各种概念以及代码操作

一、基本概念

* 每个结点最多有两棵子树,左子树和右子树,次序不可以颠倒。

性质:

1. 非空二叉树的第n层上至多有2^(n-1)个元素。

2. 深度为h的二叉树至多有2^h-1个结点。

* 满二叉树:所有终端都在同一层次,且非终端结点的度数为2。

在满二叉树中若其深度为h,则其所包含的结点数必为2^h-1。

* 完全二叉树:只有最下面的两层结点度能够小于2,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树。

* 图样



树的三种遍历方式

前序遍历:根节点->左子树->右子树

中序遍历:左子树->根节点->右子树

后序遍历:左子树->右子树->根节点

例如:求下面树的三种遍历



前序遍历:abdefgc

中序遍历:debgfac

后序遍历:edgfbca

最优二叉树

又名哈夫曼树,定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

二叉查找树(Binary Search Tree)

二叉查找树(Binary Search Tree),(又:二叉搜索树二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

二叉查找树的插入:从根节点进行对比,小于根节点,在根节点左子树进行对比;大于根节点,在根节点右子树进行对比。一直重复上述过程,当找到节点为空的地方插入。

二叉树的删除

被删除节点没有子树的情况,直接删除,并修改对应父节点的指针为空。

对于只有一个子树的情况,考虑将其子树作为其父节点的子树,关于是左还是右,根据被删除的节点确定。

最复杂的是有两个子数的情况,可以考虑两种方法,都是同样的思想:用被删除节点A的左子树的最右节点或者A的右子树的最左节点作为替代A的节点,并修改相应的最左或最右节点的父节点的指针,修改方法类似2 。

图样



各种二叉树操作代码算法

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
* @author 高远</n>
* 邮箱  wgyscsf@163.com</n>
* 编写日期   2017-3-17下午2:31:24</n>
* </n>
*/
public class MyBinaryTreeList {
BinaryTree root;

// 定义二叉树
class BinaryTree {
BinaryTree left;
BinaryTree right;
int value;

public BinaryTree(int value) {
this.value = value;
}

public BinaryTree() {
root = null;
}
}

// 向二叉查找树插入数据
boolean add(BinaryTree binaryTree,int value) {
if (root == null) {
root = new BinaryTree(value);
} else {
if (value < binaryTree.value) {
if (binaryTree.left == null) {
binaryTree.left = new BinaryTree(value);
} else {
add(binaryTree.left, value);
}
} else {
if (binaryTree.right == null) {
binaryTree.right = new BinaryTree(value);
} else {
add(binaryTree.right, value);
}
}
}
return true;
}

// 前序遍历
void preScanner(BinaryTree binaryTree) {
if (binaryTree == null)
return;
System.out.print(binaryTree.value + ",");
preScanner(binaryTree.left);
preScanner(binaryTree.right);
}

// 中序遍历
void midScanner(BinaryTree binaryTree) {
if (binaryTree == null)
return;
midScanner(binaryTree.left);
System.out.print(binaryTree.value + ",");
midScanner(binaryTree.right);
}

// 后序遍历
void finScanner(BinaryTree binaryTree) {
if (binaryTree == null)
return;
finScanner(binaryTree.left);
finScanner(binaryTree.right);
System.out.print(binaryTree.value + ",");
}

// 递归求树的深度
int treeDeepByRecursion(BinaryTree binaryTree) {
if (binaryTree == null)
return 0;
int leftDeep = treeDeepByRecursion(binaryTree.left);
int rightDeep = treeDeepByRecursion(binaryTree.right);
return leftDeep > rightDeep ? leftDeep + 1 : rightDeep + 1;
}

/*
* 非递归求树的深度,思路:
* 1.维护一个当前队列节点的长度a,在初始化一个长度为零的变量b。变量每次加一,取出一个数据,同时加入该节点的左右孩纸。当a=b,结束当前循环。
* 2. 结束循环前维护一个深度l,深度l++。 3. 重复1,2。当队列时结束。
*/
int treeDeepByNoRecursion(BinaryTree binaryTree) {
if (binaryTree == null)
return 0;
// 维护一个队列,
LinkedList<BinaryTree> binaryTreeList = new LinkedList<>();
binaryTreeList.offer(binaryTree);
int currentIndex;
int lastIndex;
BinaryTree currentBinaryTree;
//深度
int leval=0;
//结束条件
while(!binaryTreeList.isEmpty()){
currentIndex=0;
lastIndex=binaryTreeList.size();
while (currentIndex < lastIndex) {
// poll取出一个元素,并从原来队列删除;peek查询第一个数据。
currentBinaryTree = binaryTreeList.poll();
currentIndex++;
// 以下是将下一层加入队列,在下次循环中进行计算
if (currentBinaryTree.left != null) {
binaryTreeList.offer(currentBinaryTree.left);
}
if (currentBinaryTree.right != null) {
binaryTreeList.offer(currentBinaryTree.right);
}
}
leval++;

}
return leval;

}

// 求树的宽度。思路和非递归求树的深度相对应。
int treeWidth(BinaryTree binaryTree) {
LinkedList<BinaryTree> linkedList = new LinkedList<>();
linkedList.offer(binaryTree);
int currentIndex;// 当前位置节点。
int lastIndex;// 当前层最大节点的数量,即当前层树的宽度。
BinaryTree currentBinaryTree;// 当前取出的节点。
int maxLen = 0;// 最大层的值。
while (!linkedList.isEmpty()) {
currentIndex = 0;
lastIndex = linkedList.size();
while (currentIndex < lastIndex) {
currentBinaryTree = linkedList.poll();
currentIndex++;
// 以下是将下一层加入队列,在下次循环中进行计算
if (currentBinaryTree.left != null) {
linkedList.offer(currentBinaryTree.left);
}
if (currentBinaryTree.right != null) {
linkedList.offer(currentBinaryTree.right);
}
}
// 处理最大层的数量
if (lastIndex > maxLen) {
maxLen = lastIndex;
}
}

return maxLen;

}

// 找出二叉树的所有深度遍历路径
ArrayList<Integer> list3 = new ArrayList<>();
ArrayList<ArrayList<Integer>> listList3 = new ArrayList<>();

private ArrayList<ArrayList<Integer>> getAllDeepPath(BinaryTree binaryTree) {
if (binaryTree == null)
return listList3;
list3.add(binaryTree.value);
if (binaryTree.left == null && binaryTree.right == null) {
// 这种写法不行,原因:@param c the collection whose elements are to be placed
// into this list
// listList3.add(list3);
listList3.add(new ArrayList<Integer>(list3));//
}
if (binaryTree.left != null)
getAllDeepPath(binaryTree.left);
if (binaryTree.right != null)
getAllDeepPath(binaryTree.right);
list3.remove(list3.size() - 1);
return listList3;
}

// 在二叉树中找出和为某一值的所有路径
List<Integer> list4 = new ArrayList<>();
List<List<Integer>> allList4 = new ArrayList<>();
private List<List<Integer>> getSpDeepTree(BinaryTree binaryTree, int target) {
if (binaryTree == null)
return allList4;
list4.add(binaryTree.value);
target -= binaryTree.value;
if (target == 0 && binaryTree.left == null && binaryTree.right == null)
allList4.add(new ArrayList<>(list4));
if (binaryTree.left != null)
getSpDeepTree(binaryTree.left, target);
if (binaryTree.right != null)
getSpDeepTree(binaryTree.right, target);

list4.remove(list4.size() - 1);
return allList4;
}

// test
public static void main(String[] args) {
int[] arr = new int[] { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 };
MyBinaryTreeList binaryTreeList = new MyBinaryTreeList();
for (int i = 0; i < arr.length; i++) {
binaryTreeList.add(binaryTreeList.root, arr[i]);
}
System.out.println("前序遍历");
binaryTreeList.preScanner(binaryTreeList.root);
System.out.println("中序遍历");
binaryTreeList.midScanner(binaryTreeList.root);
System.out.println("后序遍历");
binaryTreeList.finScanner(binaryTreeList.root);
System.out.println();
System.out.println("递归树的深度:"
+ binaryTreeList.treeDeepByRecursion(binaryTreeList.root));
System.out.println("非递归树的深度:"
+ binaryTreeList.treeDeepByNoRecursion(binaryTreeList.root));
System.out.println("递归树的宽度:"
+ binaryTreeList.treeWidth(binaryTreeList.root));

System.out.println("在二叉树中找所有路径2:");
ArrayList<ArrayList<Integer>> findPath3 = binaryTreeList
.getAllDeepPath(binaryTreeList.root);
for (List<Integer> arrayList : findPath3) {
for (Integer integer : arrayList) {
System.out.print(integer + ",");
}
System.out.println();
}

System.out.println("在二叉树中找出和为某一值的所有路径2:");
List<List<Integer>> findPath4 = binaryTreeList.getSpDeepTree(
binaryTreeList.root, 12);
for (List<Integer> arrayList : findPath4) {
for (Integer integer : arrayList) {
System.out.print(integer + ",");
}
System.out.println();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐