在前面总结的链表是一种一对一的关系,而有一种一对多的关系就是树。树也是由一个一个的结点组成的,每一个结点都可以看成一棵树。每一个结点只能有一个父结点,而子结点可以有多个,没有父结点的结点称为根结点,在一棵树中,根结点有且仅有一个。根结点的子结点又可以当成是一棵树,称为子树。没有子结点的结点称为叶子结点。在树结构中,最常用的时二叉树,即每个结点至多只有两颗子树。
现在我们来自定义一颗二叉树,要构造一颗二叉树,首先要有结点,所以首先要先定义一个结点类TreeNode,然后定义结点的属性,即数据域,指向父结点的对象和指向两个子结点的对象以及设置和得到这些属性的相关方法,具体代码如下:
/**
* 二叉树结点类
* @author lenovo
*
*/
public class TreeNode {
private Object obj;
private TreeNode parent;
private TreeNode Lchild;
private TreeNode Rchild;
//构造方法
public TreeNode(Object obj){
this.obj = obj;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
public TreeNode getParent() {
return parent;
}
public void setParent(TreeNode parent) {
this.parent = parent;
}
public TreeNode getLchild() {
return Lchild;
}
public void setLchild(TreeNode lchild) {
Lchild = lchild;
}
public TreeNode getRchild() {
return Rchild;
}
public void setRchild(TreeNode rchild) {
Rchild = rchild;
}
}
定义了结点之后,就可以创建根结点以及其他子结点,然后再建立引用关系就可以手工建成一颗二叉树了,具体代码如下所示:
/**
* 手工创建二叉树
* @return:返回树的根结点
*/
public TreeNode createTree(){
//创建根结点
TreeNode root = new TreeNode("根结点");
TreeNode lchild = new TreeNode("左孩子");
TreeNode rchild = new TreeNode("右孩子");
TreeNode llchild = new TreeNode("左左孩子");
TreeNode lrchild = new TreeNode("左右孩子");
TreeNode rlchild = new TreeNode("右左孩子");
TreeNode rrchild = new TreeNode("右右孩子");
TreeNode lllchild = new TreeNode("左左左孩子");
TreeNode llrchild = new TreeNode("左左右孩子");
//建立引用关系
root.setLchild(lchild);
root.setRchild(rchild);
lchild.setParent(root);
rchild.setParent(root);
lchild.setLchild(llchild);
lchild.setRchild(lrchild);
llchild.setParent(lchild);
lrchild.setParent(lchild);
rchild.setLchild(rlchild);
rchild.setRchild(rrchild);
rlchild.setParent(rchild);
rrchild.setParent(rchild);
llchild.setLchild(lllchild);
llchild.setRchild(llrchild);
lllchild.setParent(llchild);
llrchild.setParent(llchild);
return root;
}
这样弄好之后,要检验是不是我们所想要的二叉树,最好的办法就是把它遍历出来。对树的遍历有三种方法,一般都是遍历左子树,再是右子树,根据根结点被遍历的顺序分为先序遍历,中序遍历,后序遍历,这里用中序遍历,具体代码如下:
/**
* 根据根结点遍历二叉树
* @param root:传入的根结点
*/
public void printTree(TreeNode root){
if (root!=null){
TreeNode Lchild = root.getLchild();
TreeNode Rchild = root.getRchild();
//递归
printTree(Lchild);
Object data = root.getObj();
System.out.print(data+"\t");
//递归
printTree(Rchild);
}
}
运行结果为:
左左左孩子
左左孩子
左左右孩子
左孩子
左右孩子
根结点
右左孩子
右孩子
右右孩子
运行结果可以证明是我们想要的二叉树。现在来总结把任意一个整型的一维数组转化为一颗线索二叉树,并且通过遍历二叉树能得到有序的数组。首先要定义遍历的规则,这里是用中序遍历的。然后是把数组的第一个元素当做二叉树的根结点,然后根据根结点的四种情况定义一个方法,即根的子左结点和子右结点都不为空;子左结点不为空,子右结点为空;子左结点为空,子右结点不为空;子左结点和子右结点都为空这四种情况,然后再用递归法,具体代码如下所示:
/**
* 根据根结点的四种情况建立二叉树
* @param num:新结点数据
* @param root:根结点
*/
public void judgeNode(int num,TreeNode root){
if (root.getLchild()==null&&root.getRchild()==null){//如果根结点的左子结点和右子结点都为空
if (num<(Integer)root.getObj()){
TreeNode node = new TreeNode(num);//创建新结点
//建立引用关系
root.setLchild(node);
node.setParent(root);
}else {
TreeNode node = new TreeNode(num);//建立新结点
//建立引用关系
root.setRchild(node);
node.setParent(root);
}
}else if (root.getLchild()!=null&&root.getRchild()==null){//根结点的左子节点不为空
if (num<(Integer)root.getObj()){
//递归
judgeNode(num,root.getLchild());
}else {
TreeNode node = new TreeNode(num);//建立新结点
//建立引用关系
root.setRchild(node);
node.setParent(root);
}
}else if (root.getLchild()==null&&root.getRchild()!=null){//根结点的右子结点不为空
if (num<(Integer)root.getObj()){
TreeNode node = new TreeNode(num);//建立新结点
//建立引用关系
root.setLchild(node);
node.setParent(root);
}else {
//递归
judgeNode(num,root.getRchild());
}
}else if (root.getLchild()!=null&&root.getRchild()!=null){//根结点的左子结点和右子结点都不为空
if (num<(Integer)root.getObj()){
//递归
judgeNode(num,root.getLchild());
}else {
//递归
judgeNode(num,root.getRchild());
}
}
}
最后再遍历数组调用此方法就可以了,代码如下:
/**
* 将数组转化为二叉树
* 定义规则:中序遍历
* @param array:传入的数组
*/
@SuppressWarnings("unused")
public TreeNode arrayToTree(int[] array){
//取数组第一个元素作为根结点
TreeNode root = new TreeNode(array[0]);
if (array==null){
throw new RuntimeException("数组为空,不能生成树!!");
}else {
for (int i=1;i<array.length;i++){
//调用方法
judgeNode(array[i],root);
}
}
return root;
}
然后随机生成一个数组检验如下:
/**
* 程序入口
* @param args
*/
public static void main(String args[]){
Random rd = new Random();
//实例化对象
Tree t = new Tree();
//随机生成数组
int[] b = new int[10];
for (int i=0;i<b.length;i++){
b[i] = rd.nextInt(100);
}
System.out.println("原有数组:");
for (int i=0;i<arr.length;i++){
System.out.print(arr[i]+"\t");
}
System.out.println();
System.out.println("生成树后,按中序遍历的数组:");
TreeNode root = arrayToTree(arr);
printTree(root);
}
运行结果:
原有数组:
3 52 26 84 93 67 79 49 4 90
生成树后,按中序遍历的数组:
3 4 26 49 52 67 79 84 90 93
至此我们已经对二叉树有了一定的了解,但是知识是无限的,学习还在继续中,总结也会陆续更新。
分享到:
相关推荐
5.线索二叉树中的线索指的是( )。 A.左孩子 B.遍历 C.指针 D.标志 6. 建立线索二叉树的目的是( )。 A. 方便查找某结点的前驱或后继 B. 方便二叉树的插入与删除 C. 方便查找某结点的双亲 D. 使二叉树的遍历...
11. 叶子结点的最小结点数:有50个叶子结点的二叉树至少有51个结点。 12. 高度为h且只有度为0和2的二叉树结点数:至少有2^h-1个结点。 13. 线索二叉树的目的:线索二叉树的引入是为了在二叉树中快速找到结点的前驱...
24. 中序线索二叉树的前驱结点:在中序线索二叉树中,有左孩子的结点且不是根结点的前驱结点是其左子树中最右叶结点,答案是D。 25. 线索二叉树:线索二叉树是一种存储结构,答案是B。 26. 线索二叉树的线索数:n...
**线索二叉树**是为了解决非递归遍历二叉树而引入的,通过在二叉链表中添加线索,使得在二叉树中查找前驱和后继变得容易。 **树、森林与二叉树的转换** 树与森林可以转化为二叉树,以便利用二叉树的高效操作。这些...
这些知识点在计算机科学的学习和实践中是非常基础且重要的,它们涉及到树的性质、高度计算、存储结构、遍历方法、完全二叉树的特性以及线索二叉树的概念。掌握这些知识对于理解更复杂的算法和数据结构至关重要。
25. **线索二叉树的定义**:线索二叉树是一种存储结构,它添加了线索来方便遍历。 26. **...** 以上分析涵盖了题目中的主要知识点,包括树和二叉树的定义、性质、遍历方式、存储结构以及它们之间的关系。这些概念...
4. **线索二叉树**:线索二叉树是在二叉链表的基础上增加线索,以便在非递归方式下进行中序或其他遍历。T所指节点没有左子树的充要条件是其左线索为空。 5. **二叉树遍历**:在非空树上,根节点没有直接前驱。...
9. **线索二叉树**:线索二叉树是在二叉链表的基础上,通过线索(指向前驱和后继结点的指针)增强查找效率。后序线索二叉树允许快速进行后序遍历。 10. **哈夫曼树与编码**:哈夫曼树是一种最优二叉树,用于数据...
1.5 小结 15 习题 16 第2章 线性表 18 2.1 线性表的类型定义 18 2.1.1 线性表的定义和特点 18 2.1.2 线性表的抽象数据类型定义 18 2.2 线性表的顺序表示和实现 19 2.2.1 线性表的顺序存储表示 19 ...
线索二叉树中某结点R没有左孩子的充要条件是R.ltag=1。 深度为k的完全二叉树至少有2^k-1个结点,至多有2^k个结点,具有n个结点的完全二叉树按层序从1开始编号,则编号最小的叶子的序号是2^k-2+1。 一个高度为h的满...
线索二叉树是逻辑结构,不是物理结构,也不是线性结构。答案是A,逻辑。 15. **森林转换为二叉树的右指针为空的结点数**: 从森林F到二叉树B的转换中,每一个树转换为二叉树时,根结点的右指针为空。森林中有n个...
18. 二叉树的链式存储结构中最常见的是二叉链表和线索二叉树。 19. 如果一个叶子结点是某子树中根遍历序列的第一个结点,那么在后根遍历序列中它必定是最后一个结点。 20. 树与二叉树的主要区别在于二叉树规定每个...
线索二叉树是一种特殊的二叉树,通过利用空闲的指针域来存放结点的直接前驱和直接后继信息,从而实现了二叉树的线索化。 Huffman 树是一种特殊的二叉树,具有最小的 WPL 值,在数据压缩和编码中有重要应用。 图是...
3. **后序线索二叉树的空指针域数**:对于非空且左右子树均不为空的二叉树,在后序线索化后,每个非叶子节点有两个空指针,而叶子节点有1个空指针,因此总空指针域数为n+1,其中n是结点数,所以答案是1。 4. **时间...
### 小结 殷人昆教授的数据结构笔记详细介绍了树与二叉树的理论知识,包括它们的定义、性质、操作及实际应用。理解并掌握这些概念对于深入学习算法和数据结构,以及解决实际问题具有重要意义。在实际编程中,这些...
14. 线索二叉树问题:后序线索二叉树无法直接求后序后继,需要遍历路径。 15. DFS的时间复杂度:深度优先搜索(DFS)的时间复杂度为O(n+e),n为顶点数,e为边数。 16. 队列操作原则:队列遵循先进先出(FIFO)原则...
2. **中序线索二叉树**:线索二叉树是在二叉树的空链域中添加线索,以支持双向遍历。具体画法需要图形化。 这些知识点涵盖了数据结构的基本概念,包括树、图、排序算法、栈、队列、哈希表和查找算法等。理解和掌握...
5.5 线索二叉树 5.6 堆 5.7 二叉查找树 5.8 选拔树 5.9 森林 5.10 不相交集合的表示 5.11 二叉树的计数 5.12 参考文献和选读材料 第6章 图 6.1 图的抽象数据类型 6.2 图的基本操作 6.3 最小代价生成树 ...
在中序线索二叉树中,查找给定结点的前序后继和后序后继是另一个关键问题。前序后继的查找通常涉及到左孩子、右孩子和父节点的角色。如果一个节点的左指针是线索,那么它的前序后继是它的右孩子;如果左右指针都是...