`
sunnymoon
  • 浏览: 89301 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

数据结构与算法(JAVA篇)之树(一)

阅读更多

 

 
/**
 * 概念介绍:
 *
 * 树:树由边连接的节点构成。
 * 多路树:节点可以多于两个。
 * 路径:顺着连接点的边从一个节点到另一个节点,所以过的节点顺序排列就称做路径。
 * 根:树的顶端节点称为根。
 * 父节点:每个节点都有一条边向上连接到另一个节点,这个节点就称为父节点。
 * 子节点:每个节点都可能有一条或多条边向下连接其它节点,下面这些节点就称为子节点。
 * 叶节点:没有子节点的节点为叶子节点或叶节点。
 * 子树:每个节点都可以作为子树的根,它和它所有的子节点都包含在子树中。
 * 访问:当程序控制流程到达某个节点时,就称为“访问”这个节点。
 * 遍历:遍历树意味着要遵循某种特定的顺序访问树中所有的节点。
 * 层:一个节点的层数是指从根开始到这个节点有多少“代”。一般根为第0层。
 * 关键字:对象中通常会有一个数据域被指定为关键字,通常使用这个关键字进行查询等操作。
 * 二叉树:如果树中每个节点最多只能有两个子节点,这样的特殊的树就是二叉树。
 * 二叉搜索树:二叉树的一个节点的左子节点的关键字值小于这个节点,右子节点的关键字值大
 *            于或等于这个父节点。
 * 平衡树与非平衡树:左子节点与左子节点对称的树为平衡树,否则就是非平衡树。
 * 完全二叉树:二叉树的最后一层都是叶子结点,其它各层都有左右子树,也叫满二叉树。
 *
 * 为什么用二叉树:1.二叉树结合了另外两种数据结构的优点:一种是有序数组,另一种是链表。
 *                在树中查找数据的速度和在有序数组中查找的速度一样快,同时插入的速度
 *                和删除的速度和链表的速度一样。
 *                2.在有序数组中插入数据项太慢:用二分查找法可以在有序数据中快速的查找
 *                特定的值,查找所需时间复杂度为O(logN)。然而插入和删除是非常低效的。
 *                3.在链表中查找太慢:链表的插入和删除操作都很快,时间复杂度是O(1)。
 *                然而查找数据项是非常低效的。
 * 二叉树的效率:时间复杂度为O(logN)。树对所有的数据存储操作都很高效。
 *
 * 程序介绍:对树的一些常用操作进行了封装,包括查询,插入,删除,遍历二叉树(中序,后序,前序)
 *          以及以树的方式显示二对树的各个结点。
 *
 */
/**
 *
 * @author SunnyMoon
 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * 定义树的结点类
 */
class Node {

    public int iData;//关键字
    public double dData;//数据项
    public Node leftChild;//左子树
    public Node rightChild;//右子树

    public void displayNode() {//输出结点内容
        System.out.print("【");
        System.out.print("关键字: "+iData);
        System.out.print(",");
        System.out.print("值:"+dData);
        System.out.print("】");
    }
}

/**
 * 定义二叉树类
 */
class Tree {

    private Node root;

    public Tree() {
        root = null;
    }

    /**
     * 查找
     * @param key
     * @return
     */
    public Node find(int key) {
        Node current = root;
        while (current.iData != key) {
            if (key < current.iData) {
                current = current.leftChild;
            } else {
                current = current.rightChild;
            }
            if (current == null) {
                return null;
            }
        }
        return current;
    }
/**
 * 插入
 * @param id
 * @param dd
 */
    public void insert(int id, double dd) {
        Node newNode = new Node();
        newNode.iData = id;
        newNode.dData = dd;
        if (root == null) {
            root = newNode;
        } else {
            Node current = root;
            Node parent;
            while (true) {
                parent = current;
                if (id < current.iData) {
                    current = current.leftChild;
                    if (current == null) {
                        parent.leftChild = newNode;
                        return;
                    }
                } else {
                    current = current.rightChild;
                    if (current == null) {
                        parent.rightChild = newNode;
                        return;
                    }
                }
            }
        }
    }

    /**
     * 删除
     * @param key
     * @return
     */
    public boolean delete(int key) {
        Node current = root;
        Node parent = root;
        boolean isLeftChild = true;

        while (current.iData != key) {
            parent = current;
            if (key < current.iData) {
                isLeftChild = true;
                current = current.leftChild;
            } else {
                isLeftChild = false;
                current = current.rightChild;
            }
            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;
    }
/**
 * 遍历二叉树
 * @param traverseType
 */
    public void traverse(int traverseType) {
        switch (traverseType) {
            case 1:
                System.out.print("\n" + "前序遍历(Preorder traversal): ");
                preOrder(root);
                break;
            case 2:
                System.out.print("\n" + "中序遍历(Inorder traversal): ");
                inOrder(root);
                break;
            case 3:
                System.out.print("\n" + "后序遍历(Postorder traversal): ");
                postOrder(root);
                break;
        }
        System.out.println();
    }
/**
 * 定义定位到后序结点方法
 * @param delNode
 * @return
 */
    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;
    }
/**
 * 前序遍历
 * @param localRoot
 */
    private void preOrder(Node localRoot) {
        if (localRoot != null) {
            System.out.print(localRoot.iData + " ");
            preOrder(localRoot.leftChild);
            preOrder(localRoot.rightChild);
        }
    }
/**
 * 中序遍历
 * @param localRoot
 */
    private void inOrder(Node localRoot) {
        if (localRoot != null) {
            inOrder(localRoot.leftChild);
            System.out.print(localRoot.iData + " ");
            inOrder(localRoot.rightChild);
        }
    }
/**
 * 后序遍历
 * @param localRoot
 */
    private void postOrder(Node localRoot) {
        if (localRoot != null) {
            postOrder(localRoot.leftChild);
            postOrder(localRoot.rightChild);
            System.out.print(localRoot.iData + " ");
        }
    }
/**
 * 把关键字按树型输出
 * ‘--’表示树中这个位置的结点不存在。
 */
    public void displayTree() {
        Stack globalStack = new Stack(1000);
        globalStack.push(root);
        int nBlanks = 32;
        boolean isRowEmpty = false;
        System.out.println(
                "-----------------------------------------------------------------------");
        while (isRowEmpty == false) {
            Stack localStack = new Stack(1000);
            isRowEmpty = true;

            for (int j = 0; j < nBlanks; j++) {
                System.out.print(" ");
            }
            while (globalStack.isEmpty() == false) {
                Node temp = (Node) globalStack.pop();
                if (temp != null) {
                    System.out.print(temp.iData);
                    localStack.push(temp.leftChild);
                    localStack.push(temp.rightChild);

                    if (temp.leftChild != null || temp.rightChild != null) {
                        isRowEmpty = false;
                    }
                } else {
                    System.out.print("..");
                    localStack.push(null);
                    localStack.push(null);
                }
                for (int j = 0; j < nBlanks * 2 - 2; j++) {
                    System.out.print(" ");
                }
            }
            System.out.println();
            nBlanks /= 2;
            while (localStack.isEmpty() == false) {
                globalStack.push(localStack.pop());
            }
        }
        System.out.println(
                "-----------------------------------------------------------------------");
    }
}

/**
 * 使用的栈
 * @author Administrator
 */
class Stack {

    private int maxSize;
    private Object[] stackArray;
    private int top;

    public Stack(int s) {
        maxSize = s;
        stackArray = new Object[maxSize];
        top = -1;
    }

    public void push(Object p) {
        stackArray[++top] = p;
    }

    public Object pop() {
        return stackArray[top--];
    }

    public Object peek() {
        return stackArray[top];
    }

    boolean isEmpty() {
        if (top == -1) {
            return true;
        } else {
            return false;
        }
    }
}
/**
 * 主方法
 * @author Administrator
 */
class TreeAaa {

    public static void main(String[] args) throws IOException {
        int value;
        Tree theTree = new Tree();
        theTree.insert(12, 1.5);
        theTree.insert(15, 2.4);
        theTree.insert(22, 5.6);
        theTree.insert(33, 7.1);
        theTree.insert(55, 3.3);
        theTree.insert(26, 8.7);
        theTree.insert(17, 2.3);
        theTree.insert(8, 6.9);
        theTree.insert(6, 8.4);
        theTree.insert(14, 7.0);
        theTree.insert(23, 1.8);
        theTree.insert(38, 2.9);

        while (true) {
            System.out.print("输入想执行的操作的英文首字母:");
            System.out.print("插入(Insert), 查找(Find), 删除(Delete), 遍历(Traverse): ");
            int choice = getChar();
            switch (choice) {
                case 's':
                    theTree.displayTree();
                    break;
                case 'i':
                    System.out.print("输入想要插入的值: ");
                    value = getInt();
                    theTree.insert(value, value + 0.9);
                    break;
                case 'f':
                    System.out.print(("输入想要查找的关键字: "));
                    value = getInt();
                    Node found = theTree.find(value);
                    if (found != null) {
                        System.out.print("成功查找: ");
                        found.displayNode();
                        System.out.print("\n");
                    } else {
                        System.out.print("不存在所查询关键字");
                    }
                    System.out.print("输入的关键字:" + value + "\n");
                    break;
                case 'd':
                    System.out.print("输入想要删除的关键字: ");
                    value = getInt();
                    boolean didDelete = theTree.delete(value);
                    if (didDelete) {
                        System.out.print("删除的值:" + value + "\n");
                    } else {
                        System.out.print("不能执行删除操作");
                    }
                    System.out.println(value);
                    //System.out.print(value + "\n");
                    break;
                case 't':
                    System.out.print("输入遍历类型 1, 2 或 3:");
                    value = getInt();
                    theTree.traverse(value);
                    break;
                default:
                    System.out.println("非法输入");
            }
        }
    }

    public static String getString() throws IOException {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);
        String s = br.readLine();
        return s;
    }

    public static char getChar() throws IOException {
        String s = getString();
        return s.charAt(0);
    }

    public static int getInt() throws IOException {
        String s = getString();
        return Integer.parseInt(s);
    }
  /**
    * 运行结果:
    * 输入想执行的操作的英文首字母:插入(Insert), 查找(Find), 删除(Delete), 遍历(Traverse): s
    *-----------------------------------------------------------------------
    *                                12
    *                8                              15
    *        6              ..              14              22
    *    ..      ..      ..      ..      ..      ..      17      33
    *  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  26  55
    * ........................................................23..38..
    *-----------------------------------------------------------------------
    *输入想执行的操作的英文首字母:插入(Insert), 查找(Find), 删除(Delete), 遍历(Traverse): i
    *输入想要插入的值: 3
    *输入想执行的操作的英文首字母:插入(Insert), 查找(Find), 删除(Delete), 遍历(Traverse): f
    *输入想要查找的关键字: 14
    *成功查找: {14,7.0}
    *输入的关键字:14
    *输入想执行的操作的英文首字母:插入(Insert), 查找(Find), 删除(Delete), 遍历(Traverse):
    */
 /**
  * 总结:
  * 树结合了数组和链表的优点,是一种非常高效的数据结构。
  */
 
4
0
分享到:
评论
6 楼 sunnymoon 2008-12-21  
xiaohuasuper 写道

期待楼主的好文章

谢谢关注,你是学生吧?
最近我研究和学习一此开源项目,没有更新算法这块请了解。
5 楼 xiaohuasuper 2008-12-19  
期待楼主的好文章
4 楼 xiaohuasuper 2008-12-19  
sunnymoon 写道

sunnymoon 写道
但是完全二叉树有一点小问题,你描述的满二叉树是包含了部分内函,这种情况下所画出的树有可能不是完全的二叉树。说的通俗一些,还有一个缺右不缺左。当h-1层的结点中如果左子结点是空的,右子结点不是空的时候,那么也不是完全的二叉树。

我的描述有问题,应该是:
完全二叉树:前h-1层是满二叉树,第h层叶子结点数:[1,2^(h-1)],并且是从左至右展开
3 楼 sunnymoon 2008-12-19  
sunnymoon 写道

xiaohuasuper 写道
看了楼主写的系列的数据结构,及算法实现受益菲浅 引用 * 平衡树与非平衡树:左子节点与左子节点对称的树为平衡树,否则就是非平衡树。&amp;nbsp; * 完全二叉树:二叉树的最后一层都是叶子结点,其它各层都有左右子树,也叫满二叉树。 楼主的关于平衡树和完全二叉树的定义是不是有问题. 平衡二叉树:是左右子树的高度的差值的&amp;lt;=| 1 | 满二叉树:结点数为2^h-1(h为树的高度) 完全二叉树:前h-1层是满二叉树,第h层叶子结点数:[1,2^(h-1)] 感谢你的指正,后来也发现了,由于工作忙没有来得及将它更新。真的应该更新了,万一被错误的概念误导了一些人的话可是很麻烦的。我会尽快更新。 再次感谢!


你的平衡二叉树,和满二叉树的概念我同意。满二叉树我会在你给的概念基础上加上形像的解释。
但是完全二叉树有一点小问题,你描述的满二叉树是包含了部分内函,这种情况下所画出的树有可能不是完全的二叉树。说的通俗一些,还有一个缺右不缺左。当h-1层的结点中如果左子结点是空的,右子结点不是空的时候,那么也不是完全的二叉树。
2 楼 sunnymoon 2008-12-19  
xiaohuasuper 写道

看了楼主写的系列的数据结构,及算法实现受益菲浅
引用
* 平衡树与非平衡树:左子节点与左子节点对称的树为平衡树,否则就是非平衡树。&nbsp; * 完全二叉树:二叉树的最后一层都是叶子结点,其它各层都有左右子树,也叫满二叉树。 楼主的关于平衡树和完全二叉树的定义是不是有问题. 平衡二叉树:是左右子树的高度的差值的&lt;=| 1 | 满二叉树:结点数为2^h-1(h为树的高度) 完全二叉树:前h-1层是满二叉树,第h层叶子结点数:[1,2^(h-1)]


感谢你的指正,后来也发现了,由于工作忙没有来得及将它更新。真的应该更新了,万一被错误的概念误导了一些人的话可是很麻烦的。我会尽快更新。
再次感谢!
1 楼 xiaohuasuper 2008-12-18  
看了楼主写的系列的数据结构,及算法实现受益菲浅

引用

* 平衡树与非平衡树:左子节点与左子节点对称的树为平衡树,否则就是非平衡树。 
* 完全二叉树:二叉树的最后一层都是叶子结点,其它各层都有左右子树,也叫满二叉树。

楼主的关于平衡树和完全二叉树的定义是不是有问题.
平衡二叉树:是左右子树的高度的差值的<=| 1 |
满二叉树:结点数为2^h-1(h为树的高度)
完全二叉树:前h-1层是满二叉树,第h层叶子结点数:[1,2^(h-1)]

相关推荐

    java数据结构与算法.pdf

    Java作为广泛应用的编程语言,其在实现数据结构和算法时有着丰富的库支持和优秀的可读性。下面将对标题和描述中提到的一些关键知识点进行详细解释。 1. **数据结构**: - **稀疏数组**:当大量数据中大部分为零或...

    数据结构与算法(JAVA语言版)

    数据结构与算法是计算机科学的基础,对于理解和解决复杂问题至关重要。...通过阅读《数据结构与算法(JAVA语言版)》这本书,你将深入理解这些概念,并能熟练运用Java语言实现它们,从而提升你的编程能力。

    数据结构与算法代码详解JAVA版

    总的来说,"数据结构与算法代码详解JAVA版"是一个很好的学习资源,通过阅读和实践其中的代码,你可以深入理解这些概念,并逐步提高你的编程能力。无论你是初学者还是经验丰富的开发者,都应该重视并不断深化对数据...

    数据结构与算法 Java版

    数据结构与算法是计算机科学的基础,对于任何编程语言来说,理解和掌握它们都是至关重要的,特别是对于Java这样的高级语言。在Java中实现数据结构和算法,能够帮助开发者更高效地解决问题,提升程序性能。 数据结构...

    数据结构与算法(Java语言版)含有源码

    本资源包含两部分:一本名为“数据结构与算法(JAVA语言版)”的PDF教程和一个“源码.zip”压缩包,提供了相关的Java实现。 1. 数据结构:数据结构是组织和存储数据的方式,它直接影响到算法的效率。常见的数据结构...

    java数据结构与算法中文版

    这本书详细介绍了数据结构和算法的基础理论及其在Java语言中的实现,是Java开发者必备的知识库之一。 数据结构是计算机科学中的基石,它研究如何组织和存储数据,以便于高效地访问和修改。书中可能涵盖了数组、链表...

    数据结构与算法分析 java语言描述第三版 源代码

    数据结构与算法分析 java语言描述第三版 源代码数据结构与算法分析 java语言描述第三版 源代码数据结构与算法分析 java语言描述第三版 源代码数据结构与算法分析 java语言描述第三版 源代码数据结构与算法分析 java...

    数据结构与算法分析(java版内含源代码)

    《数据结构与算法分析》是计算机科学领域的一本经典著作,尤其在Java版本中,它深入探讨了如何在Java编程语言中实现各种数据结构和算法。这本书不仅提供了理论知识,还通过提供源代码实例,帮助读者更好地理解和应用...

    数据结构与算法Java语言描述

    Java作为一门广泛使用的编程语言,在数据结构与算法的教学和学习中占据着非常重要的地位。掌握数据结构与算法是进行高效编程和解决复杂问题的基础。本系列文章将系统地讲解Java中的数据结构和算法,同时通过实例来...

    数据结构与算法分析:Java语言描述 清晰中文+源代码

    《数据结构与算法分析:Java语言描述 第2版 》是国外数据结构与算法分析方面的经典教材 使用卓越的Java编程语言作为实现工具讨论了数据结构(组织大量数据的方法)和算法分析(对算法运行时间的估计) 随着计算机速度...

    Java数据结构和算法

    Java数据结构和算法 Java数据结构和算法 Java数据结构和算法 Java数据结构和算法 Java数据结构和算法 Java数据结构和算法 Java数据结构和算法 Java数据结构和算法

    数据结构与算法(java版)

    数据结构与算法是计算机科学的基础,对于理解和解决复杂问题至关重要。在Java环境下,这些概念的实现使得程序设计更加高效和优化。以下将详细介绍标题和描述中提到的关键知识点: 1. **栈与队列**: - 栈(Stack)...

    Java 数据结构与算法+源代码 高清版

    这份“Java数据结构与算法+源代码高清版”资源旨在帮助开发者深入理解并掌握这些关键概念。 首先,让我们来探讨数据结构。数据结构是组织和存储数据的方式,它为算法提供了基础。常见的数据结构包括数组、链表、栈...

    数据结构与算法JAVA版

    本资料包“数据结构与算法JAVA版”聚焦于这个核心主题,包含了用Java实现的各种数据结构和算法。 1. **数据结构**: - **数组**:是最基本的数据结构,提供了固定大小的存储空间,通过索引访问元素。Java中的数组...

    数据结构与算法 java版

    《Java数据结构与算法.pdf》是一本中文版的教程,它涵盖了数据结构如数组、链表、栈、队列、树、图、哈希表等的基本概念和实现。这些数据结构是解决复杂问题的基础,比如搜索、排序、优化存储和提高查询效率。在Java...

    数据结构与算法分析--java语言描述.pdf

    数据结构与算法分析--java语言描述.pdf

    数据结构与算法分析java版

    《数据结构与算法分析Java版》是一本由Robert Lafore撰写的书籍,该书详细介绍了如何利用Java编程语言来实现和操作各种数据结构和算法。全书共分为六个部分,分别涵盖了数据结构的基本概念、数组、简单的排序算法、...

    Java数据结构和算法.pdf

    Java数据结构和算法.pdf

Global site tag (gtag.js) - Google Analytics