《java常用算法手册》 第二章 数据结构 树 图

本文深入探讨了二叉搜索树的特性与操作,包括插入、查找、删除节点的方法及其复杂度分析,阐述了其如何结合数组与链表优点,成为高效的数据结构。

 前面我们介绍数组的数据结构,我们知道对于有序数组,查找很快,并介绍可以通过二分法查找,但是想要在有序数组中插入一个数据项,就必须先找到插入数据项的位置,然后将所有插入位置后面的数据项全部向后移动一位,来给新数据腾出空间,平均来讲要移动N/2次,这是很费时的。同理,删除数据也是。

  然后我们介绍了另外一种数据结构——链表,链表的插入和删除很快,我们只需要改变一些引用值就行了,但是查找数据却很慢了,因为不管我们查找什么数据,都需要从链表的第一个数据项开始,遍历到找到所需数据项为止,这个查找也是平均需要比较N/2次。

  那么我们就希望一种数据结构能同时具备数组查找快的优点以及链表插入和删除快的优点,于是 树 诞生了。

 

深度为路径长度

 

 A(D(I(N,M(Q,P)),H),C(G,F(J)),B(E(L(O),K)))

 

 

 

//二叉排序树
//我们就希望一种数据结构能同时具备数组查找快的优点以及链表插入和删除快的优点,于是 树 诞生了。
//https://www.cnblogs.com/ysocean/p/8032642.html
//如果我们给二叉树加一个额外的条件,就可以得到一种被称作二叉搜索树(binary search tree)的特殊二叉树。
//二叉搜索树要求:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

//待插入的节点也需要从根节点开始进行比较,小于根节点则与根节点左子树比较,反之则与右子树比较,直到左子树为空或右子树为空,则插入到相应为空的位置
    //,在比较的过程中要注意保存父节点的信息 及 待插入的位置是父节点的左子树还是右子树,才能插入到正确的位置。

 

 删除节点

删除节点是二叉搜索树中最复杂的操作,删除的节点有三种情况,前两种比较简单,但是第三种却很复杂。

  1、该节点是叶节点(没有子节点)

  2、该节点有一个子节点

  3、该节点有两个子节点

 

package LineStructure;
//二叉排序树
//我们就希望一种数据结构能同时具备数组查找快的优点以及链表插入和删除快的优点,于是 树 诞生了。
//https://www.cnblogs.com/ysocean/p/8032642.html
//如果我们给二叉树加一个额外的条件,就可以得到一种被称作二叉搜索树(binary search tree)的特殊二叉树。
//二叉搜索树要求:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
public class LinkedTree<T> extends Object {

	Node root;

	private class Node {
		private int data;
		private Node leftChild;
		private Node rightChild;

		public Node(int data) {
			this.data = data;
		}
		
		public int getData() {
			return data;
		}

	}

	public LinkedTree() {

	}

	//
	public LinkedTree(Node root) {
		this.root = root;
	}

	// get root
	public Node getRoot() {
		return this.root;
	}

	// set root
	public void setRoot(Node root) {
		this.root = root;
	}

	//待插入的节点也需要从根节点开始进行比较,小于根节点则与根节点左子树比较,反之则与右子树比较,直到左子树为空或右子树为空,则插入到相应为空的位置
	//,在比较的过程中要注意保存父节点的信息 及 待插入的位置是父节点的左子树还是右子树,才能插入到正确的位置。
	  public Boolean insert(int data) {
			String error = null;
			Node node = new Node(data);
			if (root == null) {
				root = node;
				root.leftChild  = null;
				root.rightChild = null;
			} else {
				//start to Search
				Node current = root;
				//保存一个 parent 用来插入时指定插入点的parent以及叶子节点
				Node parent = null;
				//searchTree
				while (true) {
					parent = current; //指定插入点的parent
					if(data < current.data) {
						current = current.leftChild; //searchLeftTree					
						if(current == null) {
							parent.leftChild = node;//指定插入点的位置
							return true;
						}
					}else {
						current = current.rightChild;
						if(current == null) {
							parent.rightChild = node;//指定插入点的位置
							return true;	
						}
					}
				} 
			}
			return false;
	    }


	public Boolean delete() {
		return null;

	}

	//查找树 注意并不是遍历 因为是二叉搜索树 所以查找时并不会遍历所有节点
	//查找节点的时间取决于这个节点所在的层数,每一层最多有2n-1个节点,总共N层共有2n-1个节点,那么时间复杂度为O(logn),底数为2。
	public Node find(int data) {
		Node temp = root;
		while(temp != null) {
			if(temp.data == data) {
				return temp;
			}else if(data < temp.data) {
				temp = temp.leftChild;
				
			}else if(data > temp.data) {
				temp = temp.rightChild;
			}
		}
		return null;
	}
	
	
	public void middleOrder(Node current) {
		if(current != null) {
			middleOrder(current.leftChild);
			System.out.println(current.data);
			middleOrder(current.rightChild);
		}
	
		
	}
	
	public void preOrder(Node current) {
		if(current != null) {
			System.out.println(current.data);
			preOrder(current.leftChild);
			preOrder(current.rightChild);
		}
		
	}
	
	public void postOrder(Node current) {
		if(current != null) {
			postOrder(current.leftChild);
			postOrder(current.rightChild);
			System.out.println(current.data);
		}
		
	}
	
	//查找最大值节点 直接找右子树
	public Node findMax() {
		Node current = root;
		Node maxNode = null;
		while(current != null) {
			current = current.rightChild;	
			maxNode = current;
		}
		return maxNode;
	}
	
	//查找最小值 直接找左子树
	public Node findMin() {
		Node current = root;
		//之前的写法 错误 current可能为空
		/*while(current != null) {
			current = current.leftChild;	
		}
		return current;*/
		Node MinNode = null;
		while(current != null) {
			current = current.leftChild;	
			MinNode = current;
		}
		return MinNode;
	}
	
	//删除节点
	
	

}

 

 

 

 

 

 

 

 

 

 

算法基础篇 **章 算法和实现算法Java语法 1.1 建立算法初步概念 1.1.1 什么是算法 1.1.2 算法的发展历史 1.1.3 算法的分类 1.2 算法相关概念的区别 1.2.1 算法与公式的关系 1.2.2 算法与程序的关系 1.2.3 算法数据结构的关系 1.3 算法的表示 1.3.1 自然语言表示 1.3.2 流程表示 1.3.3 N-S表示 1.3.4 伪代码表示 1.4 算法的性能评价 1.4.1 时间复杂度 1.4.2 空间复杂度 1.5 一个算法实例 1.5.1 查找数字 1.5.2 创建项目 1.5.3 编译执行 1.6 Java程序的基本结构 1.6.1 类是一个基本单元 1.6.2 main方法 1.6.3 自定义方法 1.6.4 System.out.println的使用 1.6.5 一个简单而完整的程序 1.7 顺序结构 1.8 分支结构 1.8.1 if...else分支结构 1.8.2 if...else嵌套 1.8.3 switch语句 1.8.4 编程实例 1.9 循环结构 1.9.1 while循环 1.9.2 do…while循环 1.9.3 for循环 1.9.4 编程实例 1.10 跳转结构 1 1.10.3 编程实例 1.11 小结 第2章 数据结构 2.1 数据结构概述 2.1.1 什么是数据结构 2.1.2 数据结构中的基本概念 2.1.3 数据结构的内容 2.1.4 数据结构的分类 2.1.5 数据结构的几种存储方式 2.1.6 数据类型 2.1.7 常用数据结构 2.1.8 选择合适的数据结构解决实际问题 2.2 线性表 2.2.1 什么是线性表 2.2.2 线性表的基本运算 2.3 顺序表结构 2.3.1 准备数据 2.3.2 初始化顺序表 2.3.3 计算顺序表长度 2.3.4 插入结点 2.3.5 追加结点 2.3.6 删除结点 2.3.7 查找结点 2.3.8 显示所有结点 2.3.9 顺序表操作实例 2.4 链表结构 2.4.1 什么是链表结构 2.4.2 准备数据 2.4.3 追加结点 2.4.4 插入头结点 2.4.5 查找结点 2.4.6 插入结点 2.4.7 删除结点 2.4.8 计算链表长度 2.4.9 显示所有结点 2.4.10 链表操作实例 2.5 栈结构 2.5.1 什么是栈结构 2.5.2 准备数据 2.5.3 初始化栈结构 2.5.4 判断空栈 2.5.5 判断满栈 2.5.6 清空栈 2.5.7 释放空间 2.5.8 入栈 2.5.9 出栈 2.5.10 读结点数据 2.5.11 栈结构操作实例 2.6 队列结构 2.6.1 什么是队列结构 2.6.2 准备数据 2.6.3 初始化队列结构 2.6.4 判断空队列 2.6.5 判断满队列 2.6.6 清空队列 2.6.7 释放空间 2.6.8 入队列 2.6.9 出队列 2.6.10 读结点数据 2.6.11 计算队列长度 2.6.12 队列结构操作实例 2.7 结构 2.7.1 什么是结构 2.7.2 的基本概念 2.7.3 二叉 2.7.4 准备数据 2.7.5 初始化二叉 2.7.6 添加结点 2.7.7 查找结点 2.7.8 获取左子 2.7.9 获取右子 2.7.10 判断空 2.7.11 计算二叉深度 2.7.12 清空二叉 2.7.13 显示结点数据 2.7.14 遍历二叉 2.7.15 结构操作实例 2.8 结构 2.8.1 什么是结构 2.8.2 的基本概念 2.8.3 准备数据 2.8.4 创建 2.8.5 清空 2.8.6 显示 2.8.7 遍历 2.8.8 结构操作实例 2.9 小结 第3章 基本算法思想 3.1 常用算法思想概述 3.2 穷举算法思想 3.2.1 穷举算法基本思想 3.2.2 穷举算法实例 3.3 递推算法思想 3.3.1 递推算法基本思想 3.3.2 递推算法实例 3.4 递归算法思想 …… 第2篇 算法应用篇 第4章 排序算法 第5章 查找算法 第6章 基本数学问题 第7章 数据结构问题 第8章 数论问题 第9章 算法经典趣题 **0章 游戏中的算法 **1章 密码学概述 **2章 压缩与解压缩算法 第3篇 算法面试篇 **3章 数学能力测试 **4章 算法面试题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值