java 搜索关键字算法_二进制搜索树算法的Java实现的详细代码(图)

本文介绍了二叉搜索树的概念、性质及其在Java中的实现。通过节点类定义,展示了搜索、插入和删除操作的详细代码。二叉搜索树允许高效查找,插入和删除操作,特别适合于动态数据集。文章还提供了测试功能的示例代码,帮助理解二叉搜索树的运作机制。
摘要由CSDN通过智能技术生成

cea140f7616fa2d5b75f3d8a266d46c2.jpg

二进制搜索树可以如下递归定义. 二进制搜索树可以是空的二进制树,也可以是满足以下属性的二进制树:

(1)如果其左子树不为空二叉排序树查找 算法,则左子树上任何节点的键的值都小于根节点的键的值.

(2)如果其右子树不为空,则右子树上任何节点的键的值都大于根节点的键的值.

(3)它的左和右子树本身就是二叉搜索树.

2e3ef6f2ed051e61e1d4e405fd245d18.png

06984ecff9e12f7d90142bd0c3ce46-0.png

在性能方面,如果二进制搜索树的所有非叶节点的左右子树的节点数保持相同(平衡),则二进制搜索树的搜索性能接近二进制搜索;但是它比连续存储器更好. 空间二进制搜索的优点是,更改二进制搜索树的结构(插入和删除节点)不需要移动很大部分的存储器数据,甚至不需要固定的开销. 二进制搜索树可以表示按顺序排列的数据集,因此二进制搜索树也称为二进制排序树,并且同一数据集可以表示为不同的二进制搜索树. 二进制搜索树的节点的数据结构定义为:

struct celltype{

records data;

celltype * lchild, * rchild;

}

typedef celltype * BST;

在Java中,节点的数据结构定义如下:

cfae62742a9c8221efc0bb01c757920b.png

package wx.algorithm.search.bst;

/**

* Created by apple on 16/7/29.

*/

/**

* @function 二叉搜索树中的节点

*/

public class Node {

//存放节点数据

int data;

//指向左子节点

Node left;

//指向右子节点

Node right;

/**

* @function 默认构造函数

* @param data 节点数据

*/

public Node(int data) {

this.data = data;

left = null;

right = null;

}

}

二进制搜索树的搜索过程从根节点开始. 如果查询关键字等于节点关键字,则它将命中;否则,如果查询关键字小于节点关键字,则输入“左子”;如果大于node关键字,则输入正确的儿子;如果左儿子或右儿子的指针为空,则报告找不到相应的关键字.

4cce57171cde5ee82deda5ac86d6f3-1.png

BST Search(keytype k, BST F){

//在F所指的二叉查找树中查找关键字为k的记录。若成功,则返回响应结点的指针,否则返回空

if(F == NULL) //查找失败

return NULL;

else if(k == F -> data.key){ //查找成功

return F;

}

else if (k < F -> data.key){ //查找左子树

return Search(k,F -> lchild);

}

else if (k > F -> data.key){ //查找右子树

return Search(k,F -> rchild);

}

}

dfcfe286960feb75473718c0b6628121.png

在将新记录R插入二进制搜索树时,应确保在插入后不会破坏二进制搜索树的结构特性. 因此二叉排序树查找 算法,为了执行插入操作,应首先找到R的位置. 搜索时,仍使用上述递归算法. 如果搜索失败,则将包含R的节点插入带有空子树的位置. 如果搜索成功,则不执行插入操作,操作结束.

4cce57171cde5ee82deda5ac86d6f3-2.png

void Insert(records R, BST &F){

//在F所指的二叉查找树中插入一个新纪录R

if(F == NULL){

F = new celltype;

F -> data = R;

F -> lchild = NULL;

F -> rchild = NULL;

}

else if (R.key < F -> data.key){

Insert(R,F -> lchild);

}else if(R.key > F -> data.key){

Insert(R,F -> rchild);

}

//如果 R.key == F -> data.key 则返回

}

4cce57171cde5ee82deda5ac86d6f3-3.png

772e0bd89de2d7e4e2522b880ae08af2.png

617e1411e59619af68882580b1f09d85.png

如果进行简单替换,则可能会遇到以下情况:

542adb56d89db2f70a331262bf543676.png

因此,我们必须在子树中选择一个合适的替换节点. 替换节点通常是右侧子树中的最小节点:

21e814300ded54ade93047f71849baf6.png

BinarySearchTree Java版本代码参考BinarySearchTree:

package wx.algorithm.search.bst;

/**

* Created by apple on 16/7/29.

*/

/**

* @function 二叉搜索树的示范代码

*/

public class BinarySearchTree {

//指向二叉搜索树的根节点

private Node root;

//默认构造函数

public BinarySearchTree() {

this.root = null;

}

/**

* @param id 待查找的值

* @return

* @function 默认搜索函数

*/

public boolean find(int id) {

//从根节点开始查询

Node current = root;

//当节点不为空

while (current != null) {

//是否已经查询到

if (current.data == id) {

return true;

} else if (current.data > id) {

//查询左子树

current = current.left;

} else {

//查询右子树

current = current.right;

}

}

return false;

}

/**

* @param id

* @function 插入某个节点

*/

public void insert(int id) {

//创建一个新的节点

Node newNode = new Node(id);

//判断根节点是否为空

if (root == null) {

root = newNode;

return;

}

//设置current指针指向当前根节点

Node current = root;

//设置父节点为空

Node parent = null;

//遍历直到找到第一个插入点

while (true) {

//先将父节点设置为当前节点

parent = current;

//如果小于当前节点的值

if (id < current.data) {

//移向左节点

current = current.left;

//如果当前节点不为空,则继续向下一层搜索

if (current == null) {

parent.left = newNode;

return;

}

} else {

//否则移向右节点

current = current.right;

//如果当前节点不为空,则继续向下一层搜索

if (current == null) {

parent.right = newNode;

return;

}

}

}

}

/**

* @param id

* @return

* @function 删除树中的某个元素

*/

public boolean delete(int id) {

Node parent = root;

Node current = root;

//记录被找到的节点是父节点的左子节点还是右子节点

boolean isLeftChild = false;

//循环直到找到目标节点的位置,否则报错

while (current.data != id) {

parent = current;

if (current.data > id) {

isLeftChild = true;

current = current.left;

} else {

isLeftChild = false;

current = current.right;

}

if (current == null) {

return false;

}

}

//如果待删除的节点没有任何子节点

//直接将该节点的原本指向该节点的指针设置为null

if (current.left == null && current.right == null) {

if (current == root) {

root = null;

}

if (isLeftChild == true) {

parent.left = null;

} else {

parent.right = null;

}

}

//如果待删除的节点有一个子节点,且其为左子节点

else if (current.right == null) {

//判断当前节点是否为根节点

if (current == root) {

root = current.left;

} else if (isLeftChild) {

//挂载到父节点的左子树

parent.left = current.left;

} else {

//挂载到父节点的右子树

parent.right = current.left;

}

} else if (current.left == null) {

if (current == root) {

root = current.right;

} else if (isLeftChild) {

parent.left = current.right;

} else {

parent.right = current.right;

}

}

//如果待删除的节点有两个子节点

else if (current.left != null && current.right != null) {

//寻找右子树中的最小值

Node successor = getSuccessor(current);

if (current == root) {

root = successor;

} else if (isLeftChild) {

parent.left = successor;

} else {

parent.right = successor;

}

successor.left = current.left;

}

return true;

}

/**

* @param deleleNode

* @return

* @function 在树种查找最合适的节点

*/

private Node getSuccessor(Node deleleNode) {

Node successsor = null;

Node successsorParent = null;

Node current = deleleNode.right;

while (current != null) {

successsorParent = successsor;

successsor = current;

current = current.left;

}

if (successsor != deleleNode.right) {

successsorParent.left = successsor.right;

successsor.right = deleleNode.right;

}

return successsor;

}

/**

* @function 以中根顺序遍历树

*/

public void display() {

display(root);

}

private void display(Node node) {

//判断当前节点是否为空

if (node != null) {

//首先展示左子树

display(node.left);

//然后展示当前根节点的值

System.out.print(" " + node.data);

//最后展示右子树的值

display(node.right);

}

}

}

测试功能:

本文来自电脑杂谈,转载请注明本文网址:

http://www.pc-fly.com/a/jisuanjixue/article-272663-1.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值