您的位置:首页 > 理论基础 > 数据结构算法

跟小刀学习 数据结构二叉树的实现

2017-05-03 21:44 295 查看
最近学习的有点累。导致二叉树学习的有点模糊

我们之前学过数组 和链表 数组插入比较慢 链表查询比较慢。这时候我们就需要使用树这种结构。都比较快

树的基本概念

:树最上面的节点称为根节点,一棵树只有一个根节点

父节点:每一个节点都有一条边向上连接到另一个节点,这个节点就是称为下面这个节点的父节点

子节点:每一个节点都有条向下连接的节点,下面的这个节点就是该节点的子节点

叶子节点:没有子节点的节点也叫叶子节点.

子树:每一个节点都可以作为一个子树的根。他和他的所有子节点组合在一起就是个子树

查找节点:从根节点开始查找,如果查找的节点值比当前节点的值小,则继续查找左子树,否则查找右子树

遍历树:遍历树是根据一个特定的顺序访问树的每一个节点,根据顺序的不同分为前序,中序,后序遍历三种。

前序遍历。

(1)访问根节点

(2)前序遍历左子树

(3)前序遍历右子树

中序遍历。

(1)中序遍历左子树

(2)访问根节点

(3)中序遍历右子树

后序遍历。

(1)后序遍历左子树

(2)后序遍历右子树

(3)访问根节点

上代码:

/**
* 二叉树的节点类
* @author Administrator
*
*/
public class Node {

public int iData;

public String sData;

public Node leftChild;
public Node rightChild;

public Node(int iData,String sData) {
this.iData = iData;
this.sData =sData;
}

public Node() {
// TODO Auto-generated constructor stub
}

public void dispalyNode(){
4000

System.out.print("{"+ iData +"}");
}

}


二叉树的具体实现

package com.chapter5_1;

public class Tree {

//根节点
public Node root;

/**
* 二叉树的插入 s
*/
public void insert(int d,String s){
//新节点
Node newNode = new Node(d,s);
//引用当前的节点
Node current = root;
//引用父节点
Node parent;

if(current == null){
root = newNode;
return ;//如果root节点为空的话,直接点添加都结束了
}

while(true){
//先将当前的节点付给一个parent. 这个节点一直在变动
parent = current;

if(d < current.iData){
//当前的节点变成刚才的左节点
current = current.leftChild;
if(current == null){
parent.leftChild =newNode;
return;
}
}else{//d >

//              变成刚才的又节点
current = current.rightChild;

if(current == null){
parent.rightChild= newNode;
return;
}

}
}
}

/**
* 查找二叉树
* @param value
* @return
*/
public Node find(int value){
Node current = root;

while(current.iData !=value){
//如果这个值比当前的节点值小,那么找左子节点
if(current.iData > value){
current = current.leftChild;
}else{
current = current.rightChild;
}

if(current == null){
return null;
}
}

return  current;

}
public void traverse(int traverseType){
switch (traverseType) {
case 1://
//前序遍历
System.out.println("前序遍历");
frontOrder(root);
break;
case 2:
System.out.println("中序遍历");
inOrder(root);
break;
case 3:
System.out.println("后序遍历");
postOrder(root);
break;

default:
break;
}
System.out.println("--------------------------------");
}

/**
* 前序遍历
* @param localNode
*/
public void frontOrder(Node localNode){

if(localNode != null){
//访问根节点
System.out.println(localNode.iData +","+localNode.sData);
//前序遍历左子树
frontOrder(localNode.leftChild);
//前序遍历右子树
frontOrder(localNode.rightChild);
}
}
/**
*  中序遍历 -
* 1.中序遍历左子树
* 2.访问根节点
* 3.中序遍历右子树(从小到大)
* @param localNode
*/
public void inOrder(Node localNode){

if(localNode != null){

//中序遍历左子树
inOrder(localNode.leftChild);
//访问根节点
System.out.println(localNode.iData +","+localNode.sData);
//中序遍历右子树
inOrder(localNode.rightChild);
}
}
/**
* 后序遍历。。先遍历左子树-右子树-访问根节点
* @param localNode
*/
public void postOrder(Node localNode){

if(localNode != null){

//后序遍历左子树
postOrder(localNode.leftChild);
//后序遍历右子树
postOrder(localNode.rightChild);
//访问根节点
System.out.println(localNode.iData +","+localNode.sData);

}
}

/**
* 删除一个节点
* 有3种情况
* 1.该节点是叶子节点
* 2.该节点只有 一个节点
* 3.该节点有俩个节点。需要找到右边节点的最小节点。(中序遍历后继。。找到)
* @param value
* @return
*/
public  boolean delete(int value){

//引用当前节点
Node current = root;
//引用父节点
Node parent = root;

//判断是否为左子节点
boolean isLeftChild  =true;
while(current.iData != value){
//先赋值
parent = current;
//如果这个值比当前的节点值小,那么找左子节点
if(current.iData > value){
current = current.leftChild;
isLeftChild  =true;
}else{
current = current.rightChild;
isLeftChild  =false;
}

if(current == null){
return false;
}
}

//删除叶子节点,也就是该节点没有子节点
if(current.leftChild == null && current.rightChild == null){
if(current == root){//删除的是根。并且根么有子子节点
root = null;
}else if(isLeftChild){//删除的叶子节点是父节点的左子节点
parent.leftChild = null;

}else{
parent.rightChild = null;
}

}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;
}
}else{//有俩个节点。。。。
Node successor = getSuccessor(current);

if(current ==root){
root = successor;

}else if(isLeftChild){
parent.leftChild = successor;
}else{
parent.rightChild = successor;
}

successor.leftChild =current.leftChild;
}
return true;
}

public Node getSuccessor(Node delNode){
Node successor = delNode;
Node successorParent = 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;

}
}


测试代码:

package com.chapter5_1;

public class Test {

public static void main(String[] args) {
Tree t = new Tree();

t.insert(10,"thinkpad");
t.insert(20,"mac");
t.insert(15,"del");
t.insert(3,"leishen");
t.insert(40,"zhangsan");
t.insert(16,"liao");
t.insert(4,"luyao");

//      System.out.println(t.root.rightChild.iData);
//      System.out.println(t.root.rightChild.leftChild.iData);
//      System.out.println(t.root.leftChild.iData);

//      Node node = t.find(15);
////        System.out.println(node.iData +", " +  node.sData);
//      node = t.find(3);
////        System.out.println(node.iData +", " +  node.sData);
t.delete(3);
//      t.traverse(1);
t.traverse(2);
//      t.traverse(3);

t.delete(16);
//      t.traverse(1);
t.traverse(2);
}
}


至于测试结果我就不贴了。很多。在删除二叉树有俩个节点的时。我没有弄明白。我先贴代码。最近比较累。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐