您的位置:首页 > 其它

算法学习----二叉树的查找、 删除、插入、遍历

2014-09-22 15:31 609 查看
算法学习----二叉树的查找、 删除、插入 、遍历

为什么要使用二叉树呢?

为什么要用到树呢?因为它通常结合了另外两种数据结构的优点:一种是有序数组,另一种是链表。在树中查找数据项的速度和在有序数组中查找一样快,并且插入数据项和删除数据项的速度也和链表一样。

这里开始程序之前先创建一个节点类,程序如下:

<span style="font-size:18px;">public class Node {
public int iData; // id
public double dData; // ElemData
public Node leftChild;
public Node rightChild;

public void display(){
System.out.print("{"+iData+","+dData+"}");
}
}</span>


A 查找
根据关键值key 查找节点比较简单,直接上代码。

<span style="font-size:18px;">public Node find (int key){
Node current = root;
while(key != current.iData){
if (key < current.iData){
current = current.leftChild;
}
else
current = current.rightChild;
if(current == null){
return null;
}
}
return current;
}</span>


B 插入
插入思想:插入一个元素,与根节点比较,如果为空,直接插入,如果相等,不插入

如果小于节点,则看左节点,左节点空则插入,不空则与左节点继续上面比较.

如果大于节点,则看右节点,右节点空则插入,不空则与右节点继续上面比较.

代码实现:
<span style="font-size:18px;">/*
****************************************
*         排序二叉树的插入                *
*  插入一个元素,与根节点比较,如果为空,直接插入,如果相等,不插入  *
*  如果小于节点,则看左节点,左节点空则插入,不空则与左节点继续上面比较.*
*  如果大于节点,则看右节点,右节点空则插入,不空则与右节点继续上面比较.*
****************************************
*/

public void insert(int id,double dd){
Node newNode = new Node();
newNode.iData = id;
newNode.dData = dd;  //get the Node

if (root == null)
root = newNode;
else {
Node current = root; //start as root
Node parent;
while(true){ //search the Node
parent = current;
if(id < current.iData){
current = current.leftChild;
if (current == null) {
parent.leftChild = newNode;
return;
}
}  //end of go to left

else {
current = current.rightChild;
if(current == null){
parent.rightChild = newNode;
return;
}
}   //end of go to right
}
}
}</span>


C 删除

删除节点是二叉搜索树常用的一般操作中最复杂的。

删除节点要从查找要删的节点开始入手,方法与前面介绍的findO和insertO相同。找到节点后,

这个要删除的节点可能会有三种情况需要考虑:

1.该节点是叶节点(没有子节点) 。

2 . 该节点只有一个子节点。

3 . 该节点有两个子节点。

其中,第一种最简单:第L种也还是比较简单的:而第三种就相当复杂。

情况一:要删除叶节点,只需要改变该节点的父节点的对应子字段的值,由指向该节点、改为null 就可以

了。要删除的节点仍然存在,但它已经不是树的一部分了。因为Java 语言有垃圾自动收集的机制,所以不需要非得把节点本身给删掉。一旦Java 意识到程序不再与这个节点有关联,就会自动把它清理出存储器。
情况二:删除的节点只有一个子节点。这类节点只有两个连接,一个是连接它的父类节点,一个是连接它的子类节点;我们需要从这个序列中“剪段”这个节点,把它的子节点直接连在其父节点上。这个过程要求改变父类节点适当的引用(左子节点还是右子节点),指向要删除节点的子节点。

情况三:删除的节点有两个子节点:主要思路是先找到其后继节点。
什么是后继节点呢?简单说就是比初始节点大的最小值。
其作用是:后继节点就是要替换该删除节点的在树中的位置节点。
如何找后继节点呢? 从要删除节点的第一个右子节点开始找.找其左子节点,一直到最后一个左子节点为空为止。这是由二叉树的性质决定的,请仔细想想。
然后,怎么删除节点呢?
其思路是: 1 把后继父节点的左子节点LeftChild置为后继节点的右子节点;
2 把后继节点的 右子节点rightChild置为要删除节点的右子节点;
3 把current从它的父节点的rightChild字段移除,把这个字段置为中继节点。
4 把current的左子节点从current移除,中继的左子节点字段置为current的左子节点。
具体代码如下:

首先在寻找中继节点的程序:
/*
* 从要删除节点的第一个右子节点开始找.找其左子节点,一直到最后一个左子节点为空为止
*/
private Node getSuccessor(Node delNode) {

Node successorParent = delNode;
Node successor = delNode;
Node current = delNode.rightChild;  //从要删除节点的第一个右子节点开始找

while(current != null){
successorParent = successor;
successor = current;
current = current.leftChild; //一直往左
}

if(successor != delNode.rightChild){ //找到的后继节点不是要删除节点的右子节点
successorParent.leftChild = successor.rightChild;
successor.rightChild = delNode.rightChild;
}
return successor;
}


然后是删除节点的程序
/*
* 1.被删除节点没有子树的情况,直接删除,并修改对应父节点的指针为空。
* 2.对于只有一个子树的情况,考虑将其子树作为其父节点的子树,关于是左还是右,根据被删除的节点确定.
* 3.最复杂的是有两个子数的情况,可以考虑两种方法,都是同样的思想:用被删除节点A的左子树的最右节点
*  或者A的右子树的最左节点作为替代A的节点,并修改相应的最左或最右节点的父节点的指针,修改方法类似
*/
public boolean delete (int key){
Node current = root;
Node parent = root;
boolean isLeftChild = true;

while(current.iData != key){ //search for the Node
parent = current;
if(key < current.iData){
isLeftChild = true;
current = current.leftChild;
}
else {
isLeftChild = false;
current = current.rightChild;
}
if(current == null){
return false;
}
} //end of while

/*
* find to delete
* 被删除节点没有子树的情况,直接删除.并修改对应父节点的指针为空
*/
if(current.leftChild == null && current.rightChild == null){
if(current == root)
root = null;
else if(isLeftChild)
parent.leftChild = null;
else
parent.rightChild = null;
}

/*
* 对于只有一个子树的情况,考虑将其子树作为其父节点的子树,关于是左还是右,根据被删除<span style="white-space:pre">		</span> *  的节点确定
*/
else if (current.rightChild == null){
if(current == root)
root = current.leftChild;
else if(isLeftChild)
parent.leftChild = current.leftChild;
else
parent.rightChild = current.leftChild;
}
else if(current.leftChild == null){
if(current == root)
root = current.rightChild;
else if(isLeftChild)
parent.leftChild = current.rightChild;
else
parent.rightChild = current.rightChild;
}
/*
* 最复杂的是有两个子数的情况
* replace with inorder successor
*/
else {
//get successor of node to delete(current)
Node successor = getSuccessor(current);

//connect parent of current to successor instead
if(current == root)
root = successor;
else if (isLeftChild)
parent.leftChild = successor;
else
parent.rightChild = successor;

//connect successor to current's left child
successor.leftChild = current.leftChild;
}//end of tow child
// (successor cannot have a left child)
return true;
} //end delete()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐