算法学习----二叉树的查找、 删除、插入、遍历
2014-09-22 15:31
609 查看
算法学习----二叉树的查找、 删除、插入 、遍历
为什么要使用二叉树呢?
为什么要用到树呢?因为它通常结合了另外两种数据结构的优点:一种是有序数组,另一种是链表。在树中查找数据项的速度和在有序数组中查找一样快,并且插入数据项和删除数据项的速度也和链表一样。
这里开始程序之前先创建一个节点类,程序如下:
A 查找
根据关键值key 查找节点比较简单,直接上代码。
B 插入
插入思想:插入一个元素,与根节点比较,如果为空,直接插入,如果相等,不插入
如果小于节点,则看左节点,左节点空则插入,不空则与左节点继续上面比较.
如果大于节点,则看右节点,右节点空则插入,不空则与右节点继续上面比较.
代码实现:
C 删除
删除节点是二叉搜索树常用的一般操作中最复杂的。
删除节点要从查找要删的节点开始入手,方法与前面介绍的findO和insertO相同。找到节点后,
这个要删除的节点可能会有三种情况需要考虑:
1.该节点是叶节点(没有子节点) 。
2 . 该节点只有一个子节点。
3 . 该节点有两个子节点。
其中,第一种最简单:第L种也还是比较简单的:而第三种就相当复杂。
情况一:要删除叶节点,只需要改变该节点的父节点的对应子字段的值,由指向该节点、改为null 就可以
了。要删除的节点仍然存在,但它已经不是树的一部分了。因为Java 语言有垃圾自动收集的机制,所以不需要非得把节点本身给删掉。一旦Java 意识到程序不再与这个节点有关联,就会自动把它清理出存储器。
情况二:删除的节点只有一个子节点。这类节点只有两个连接,一个是连接它的父类节点,一个是连接它的子类节点;我们需要从这个序列中“剪段”这个节点,把它的子节点直接连在其父节点上。这个过程要求改变父类节点适当的引用(左子节点还是右子节点),指向要删除节点的子节点。
情况三:删除的节点有两个子节点:主要思路是先找到其后继节点。
什么是后继节点呢?简单说就是比初始节点大的最小值。
其作用是:后继节点就是要替换该删除节点的在树中的位置节点。
如何找后继节点呢? 从要删除节点的第一个右子节点开始找.找其左子节点,一直到最后一个左子节点为空为止。这是由二叉树的性质决定的,请仔细想想。
然后,怎么删除节点呢?
其思路是: 1 把后继父节点的左子节点LeftChild置为后继节点的右子节点;
2 把后继节点的 右子节点rightChild置为要删除节点的右子节点;
3 把current从它的父节点的rightChild字段移除,把这个字段置为中继节点。
4 把current的左子节点从current移除,中继的左子节点字段置为current的左子节点。
具体代码如下:
首先在寻找中继节点的程序:
然后是删除节点的程序
为什么要使用二叉树呢?
为什么要用到树呢?因为它通常结合了另外两种数据结构的优点:一种是有序数组,另一种是链表。在树中查找数据项的速度和在有序数组中查找一样快,并且插入数据项和删除数据项的速度也和链表一样。
这里开始程序之前先创建一个节点类,程序如下:
<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()
相关文章推荐
- 二叉树 BinaryTree (先序、中序、后序遍历 节点查找、插入、删除 完整类) Java数据结构与算法
- 二叉树的学习(四种遍历方法,搜索,插入,删除等)
- 二叉树2(二叉查找树的插入、查找、删除、遍历)
- 二叉树 BinaryTree (先序、中序、后序遍历 节点查找、插入、删除 完整类) Java数据结构与算法
- 算法学习-数据结构之链表操作,创建,插入,删除,查找。
- 二叉树的链式实现(插入,查找,遍历,删除)
- 二叉树 BinaryTree (先序、中序、后序遍历 节点查找、插入、删除 完整类) Java数据结构与算法
- C++ 二叉树(创建,遍历,查找,插入,删除)『菜鸟版』
- 二叉树的遍历、查找、插入以及删除
- 二叉树的查找,插入,删除,遍历,最小值,最大值 操作
- 二叉树的创建,遍历,查找,删除,插入,修改
- 顺序二叉树的建立、查找、删除、插入、替换、遍历
- 二叉树的遍历 插入 查找 删除 最大值 最小值 前驱 后继节点的查找
- 单链表建立,插入,删除,查找,遍历操作
- 二叉查找树原理分析及查找、插入、删除、遍历实现
- 常见数据结构查找、插入、删除、遍历性能比较 常见排序算法的比较(图)
- 《Delphi 算法与数据结构》学习与感悟[8]: 单向链表的添加、删除与遍历
- 二叉排序树的构造,插入,遍历,查找,删除
- 二叉搜身树(BST)的插入、删除、查找、遍历
- 算法:二叉排序树的删除节点策略及其图形化(二叉树查找)