<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>那美克星人的家爱博客</title>
    <description>美酒就像毒药</description>
    <link>http://leon-a.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>区间树</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://leon-a.javaeye.com/blog/216224" style="color:red;">http://leon-a.javaeye.com/blog/216224</a>&nbsp;
          发表时间: 2008年07月18日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
package acmcode;


/**
 * @author Leon.Chen
 *
 */
public class IntervalTree {


    /**
     * 红
     */
    private static final String RED = "red";

    /**
     * 黑
     */
    private static final String BLACK = "black";

    /**
     * 根节点
     */
    private RBNode root;

    /**
     * 左旋转
     * 
     * @param x
     */
    private void leftRotate(RBNode x) {
        RBNode y = x.right;
        x.right = y.left;
        y.left.parent = x;
        x.setMinPointAndMaxPoint();
        y.parent = x.parent;
        if (x.parent == null) {
            root = y;
        } else {
            if (x == x.parent.left) {
                x.parent.left = y;
            } else {
                x.parent.right = y;
            }
        }
        y.left = x;
        x.parent = y;
        y.setMinPointAndMaxPoint();
    }

    /**
     * 右旋转
     * 
     * @param y
     */
    private void rightRotate(RBNode y) {
        RBNode x = y.left;
        y.left = x.right;
        x.right.parent = y;
        y.setMinPointAndMaxPoint();
        x.parent = y.parent;
        if (y.parent == null) {
            root = x;
        } else {
            if (y == y.parent.left) {
                y.parent.left = x;
            } else {
                y.parent.right = x;
            }
        }
        x.right = y;
        y.parent = x;
        x.setMinPointAndMaxPoint();
    }

    /**
     * 红黑树插入方法
     * 
     * @param z
     */
    public void RBInsert(RBNode z) {
        if (root == null) {
            root = z;
            root.color = BLACK;
            root.setMinPointAndMaxPoint(z);
        } else {
            RBNode x = root;
            RBNode y = null;
            while (isNotNilNode(x)) {
                y = x;
                x.setMinPointAndMaxPoint(z);
                if (z.value.compareTo(x.value) &lt; 0) {
                    x = x.left;
                } else {
                    x = x.right;
                }
            }
            if (z.value.compareTo(y.value) &lt; 0) {
                y.left = z;
            } else {
                y.right = z;
            }
            z.color = RED;
            z.setMinPointAndMaxPoint(z);
            z.parent = y;
        }
        z.left = new RBNode(BLACK);
        z.right = new RBNode(BLACK);
        RBInsertFixUp(z);
    }

    /**
     * 解决插入冲突
     * 
     * @param z
     */
    private void RBInsertFixUp(RBNode z) {
        while (z.parent != null && z.parent.color.equals(RED)) {
            if (z.parent == z.parent.parent.left) {
                RBNode y = z.parent.parent.right;
                if (y.color.equals(RED)) {
                    z.parent.color = BLACK;
                    y.color = BLACK;
                    z.parent.parent.color = RED;
                    z = z.parent.parent;
                } else if (z == z.parent.right) {
                    z = z.parent;
                    leftRotate(z);
                } else if (z == z.parent.left) {
                    z.parent.color = BLACK;
                    z.parent.parent.color = RED;
                    rightRotate(z.parent.parent);
                }
            } else {
                RBNode y = z.parent.parent.left;
                if (y.color.equals(RED)) {
                    z.parent.color = BLACK;
                    y.color = BLACK;
                    z.parent.parent.color = RED;
                    z = z.parent.parent;
                } else if (z == z.parent.left) {
                    z = z.parent;
                    rightRotate(z);
                } else if (z == z.parent.right) {
                    z.parent.color = BLACK;
                    z.parent.parent.color = RED;
                    leftRotate(z.parent.parent);
                }
            }
        }
        root.color = BLACK;
    }

    /**
     * @param deleteNode
     */
    public void RBDelete(RBNode deleteNode) {
        RBNode y = null;
        RBNode z = serach(deleteNode.value);
        if (isNilNode(z.left) || isNilNode(z.right)) {
            y = z;
        } else {
            y = treeSuccessor(z);
        }
        RBNode x = null;
        if (isNotNilNode(y.left)) {
            x = y.left;
        } else {
            x = y.right;
        }
        x.parent = y.parent;
        if (isNilNode(y.parent)) {
            root = x;
        } else {
            if (y == y.parent.left) {
                y.parent.left = x;
            } else {
                y.parent.right = x;
            }
        }
        if (y != z) {
            z.value = y.value;
        }
        if (y.color.equals(BLACK)) {
            RBDeleteFixUp(x);
        }
    }

    /**
     * @param x
     */
    private void RBDeleteFixUp(RBNode x) {
        // 解决黑黑冲突,完善中
        while (x != root && x.color.equals(BLACK)) {
            if (x == x.parent.left) {
                RBNode w = x.parent.right;
                if (w.color.equals(RED)) {
                    w.color = BLACK;
                    x.parent.color = RED;
                    leftRotate(x.parent);
                    w = x.parent.right;
                } else if (w.left.color.equals(BLACK) && w.right.color.equals(BLACK)) {
                    w.color = RED;
                    x = x.parent;
                } else if (w.right.color.equals(BLACK)) {
                    w.left.color = BLACK;
                    w.color = RED;
                    rightRotate(w);
                    w = x.parent.right;
                } else if (w.left.color.equals(BLACK)) {
                    w.color = x.parent.color;
                    x.parent.color = BLACK;
                    w.right.color = BLACK;
                    leftRotate(x.parent);
                    x = root;
                }
            } else {
                RBNode w = x.parent.left;
                if (w.color.equals(RED)) {
                    w.color = BLACK;
                    x.parent.color = RED;
                    rightRotate(x.parent);
                    w = x.parent.left;
                } else if (w.left.color.equals(BLACK) && w.right.color.equals(BLACK)) {
                    w.color = RED;
                    x = x.parent;
                } else if (w.left.color.equals(BLACK)) {
                    w.right.color = BLACK;
                    w.color = RED;
                    leftRotate(w);
                    w = x.parent.left;
                } else if (w.right.color.equals(BLACK)) {
                    w.color = x.parent.color;
                    x.parent.color = BLACK;
                    w.left.color = BLACK;
                    rightRotate(x.parent);
                    x = root;
                }
            }
        }
        x.color = BLACK;
    }

    /**
     * 找后继
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treeSuccessor(RBNode node) {
        if (node.right != null) {
            return treeMiniMum(node.right);
        }
        RBNode currentNode = getParentNode(node);
        while (currentNode != null && node == currentNode.right) {
            node = currentNode;
            currentNode = getParentNode(node);
        }
        return currentNode;
    }

    /**
     * 找前驱
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treePrecursor(RBNode node) {
        if (node.left != null) {
            return treeMaxiMum(node.left);
        }
        RBNode currentNode = getParentNode(node);
        while (currentNode != null && node == currentNode.left) {
            node = currentNode;
            currentNode = getParentNode(node);
        }
        return currentNode;
    }

    /**
     * 最大节点
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treeMaxiMum(RBNode node) {
        while (isNotNilNode(node.right)) {
            node = node.right;
        }
        return node;
    }

    /**
     * 最小节点
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treeMiniMum(RBNode node) {
        while (isNotNilNode(node.left)) {
            node = node.left;
        }
        return node;
    }

    /**
     * 找节点的父节点
     * 
     * @param node
     * @return TreeNode
     */
    public RBNode getParentNode(RBNode node) {
        RBNode current = root;
        RBNode trailCurrent = null;
        while (isNotNilNode(current)) {
            if (current.value.compareTo(node.value) == 0) {
                break;
            }
            trailCurrent = current;
            if (node.value.compareTo(current.value) &lt; 0) {
                current = current.left;
            } else {
                current = current.right;
            }
        }
        return trailCurrent;
    }

    /**
     * 搜索
     * 
     * @param value
     * @return TreeNode
     */
    public RBNode serach(RBValue value) {
        return treeSerach(root, value);
    }

    /**
     * 搜索
     * 
     * @param node
     * @param value
     * @return TreeNode
     */
    public RBNode treeSerach(RBNode node, RBValue value) {
        if (isNotNilNode(node) && node.value.compareTo(value) == 0) {
            return node;
        }
        if (value.compareTo(node.value) &lt; 0) {
            return treeSerach(node.left, value);
        } else {
            return treeSerach(node.right, value);
        }
    }

    /**
     * 中序遍历
     * 
     * @param node
     */
    public void inOrder(RBNode node) {
        if (isNotNilNode(node)) {
            inOrder(node.left);
            System.out.println(node.value+","+node.color);
            inOrder(node.right);
        }
    }
    
    /**
     * 先序遍历
     * 
     * @param node
     */
    public void perOrder(RBNode node) {
        if (isNotNilNode(node)) {
            System.out.println(node.value+","+node.color);
            perOrder(node.left);
            perOrder(node.right);
        }
    }

    /**
     * @param node
     * @return 是否为NIL[T]节点
     */
    private boolean isNotNilNode(RBNode node) {
        return node != null && node.value != null;
    }

    /**
     * @param node
     * @return 是否为NIL[T]节点
     */
    private boolean isNilNode(RBNode node) {
        return !isNotNilNode(node);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        IntervalTree tree = new IntervalTree();
        tree.RBInsert(new RBNode(new RBValue(0,3)));
        tree.RBInsert(new RBNode(new RBValue(5,8)));
        tree.RBInsert(new RBNode(new RBValue(6,10)));
        tree.RBInsert(new RBNode(new RBValue(8,9)));
        tree.RBInsert(new RBNode(new RBValue(15,23)));
        tree.RBInsert(new RBNode(new RBValue(16,21)));
        tree.RBInsert(new RBNode(new RBValue(17,19)));
        tree.RBInsert(new RBNode(new RBValue(19,20)));
        tree.RBInsert(new RBNode(new RBValue(25,30)));
        tree.RBInsert(new RBNode(new RBValue(26,26)));
        System.out.println("=================");
        System.out.println("root = "+tree.root.value);
        System.out.println("=================");
        tree.inOrder(tree.root);
        System.out.println("=================");
        tree.perOrder(tree.root);
    }

}
</pre><br /><pre name="code" class="java">
package acmcode;

/**
 * @author Leon.Chen
 *
 */
public class RBNode {

    /**
     * 
     */
    public RBNode parent;

    /**
     * 
     */
    public RBNode left;

    /**
     * 
     */
    public RBNode right;

    /**
     * 
     */
    public RBValue value;

    /**
     * 
     */
    public String color;

    /**
     * @param color
     */
    public RBNode(String color) {
        this.color = color;
    }

    /**
     * 
     */
    public RBNode() {

    }

    /**
     * @param value
     */
    public RBNode(RBValue value) {
        this.value = value;
    }
    
    /**
     * @param node
     */
    public void setMinPointAndMaxPoint(RBNode node) {
        if(node.value.startPoint&lt;this.value.minPoint) {
            this.value.minPoint = node.value.startPoint;
        }
        if(node.value.endPoint>this.value.maxPoint) {
            this.value.maxPoint = node.value.endPoint;
        }
    }
    
    /**
     * 
     */
    public void setMinPointAndMaxPoint() {
        int min = 0;
        int max = 0;
        if (this.left.value == null && this.right.value == null) {
            min = this.value.startPoint;
            max = this.value.endPoint;
        } else {
            min = getMin();
            max = getMax();
        }
        this.value.minPoint = min;
        this.value.maxPoint = max;
    }
    
    /**
     * @return min
     */
    private int getMin() {
        RBNode left = this.left;
        RBNode right = this.right;
        int temp = getMin(left,right);
        if(this.value.startPoint > temp) {
            return temp;
        }
        return this.value.startPoint;
    }
    
    /**
     * @return max
     */
    private int getMax() {
        RBNode left = this.left;
        RBNode right = this.right;
        int temp = getMax(left,right);
        if(this.value.endPoint >temp) {
            return this.value.endPoint;
        }
        return temp;
    }
    
    /**
     * @param node1
     * @param node2
     * @return min
     */
    private int getMin(RBNode node1, RBNode node2) {
        if (node1.value == null && node2.value == null) {
            return 2147483647;
        }
        if (node1.value == null) {
            return node2.value.minPoint;
        }
        if (node2.value == null) {
            return node1.value.minPoint;
        }
        return (node1.value.minPoint &lt; node2.value.minPoint ? node1.value.minPoint : node2.value.minPoint);
    }
    
    /**
     * @param node1
     * @param node2
     * @return max
     */
    private int getMax(RBNode node1, RBNode node2) {
        if (node1.value == null && node2.value == null) {
            return 0;
        }
        if (node1.value == null) {
            return node2.value.maxPoint;
        }
        if (node2.value == null) {
            return node1.value.maxPoint;
        }
        return (node1.value.maxPoint &lt; node2.value.maxPoint ? node2.value.maxPoint : node1.value.maxPoint);
    }
}
</pre><br /><pre name="code" class="java">
package acmcode;

/**
 * @author Leon.Chen
 *
 */
public class RBValue {

    /**
     * 
     */
    public int startPoint;

    /**
     * 
     */
    public int endPoint;

    /**
     * 初始化minPoint为无穷大
     */
    public int minPoint = 2147483647;

    /**
     * 
     */
    public int maxPoint;

    /**
     * @param startPoint
     * @param endPoint
     */
    public RBValue(int startPoint, int endPoint) {
        this.startPoint = startPoint;
        this.endPoint = endPoint;
    }

    /**
     * @param otherValue
     * @return 比较结果
     */
    public int compareTo(RBValue otherValue) {
        int thisVal = this.startPoint;
        int anotherVal = otherValue.startPoint;
        return (thisVal &lt; anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
    }

    public String toString() {
        return "[" + startPoint + "," + endPoint + "]" + " , [" + minPoint + "," + maxPoint + "]";
    }
}
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://leon-a.javaeye.com/blog/216224#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 18 Jul 2008 15:47:41 +0800</pubDate>
        <link>http://leon-a.javaeye.com/blog/216224</link>
        <guid>http://leon-a.javaeye.com/blog/216224</guid>
      </item>
      <item>
        <title>红黑树初版</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://leon-a.javaeye.com/blog/215494" style="color:red;">http://leon-a.javaeye.com/blog/215494</a>&nbsp;
          发表时间: 2008年07月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
package acmcode;

/**
 * Red-Black Tree
 * 
 * @author Leon.Chen
 */
public class RBTree {

    /**
     * 红
     */
    private static final String RED = "red";

    /**
     * 黑
     */
    private static final String BLACK = "black";

    /**
     * 根节点
     */
    private RBNode root;

    /**
     * 左旋转
     * 
     * @param x
     */
    private void leftRotate(RBNode x) {
        RBNode y = x.right;
        x.right = y.left;
        y.left.parent = x;
        y.parent = x.parent;
        if (x.parent == null) {
            root = y;
        } else {
            if (x == x.parent.left) {
                x.parent.left = y;
            } else {
                x.parent.right = y;
            }
        }
        y.left = x;
        x.parent = y;
    }

    /**
     * 右旋转
     * 
     * @param y
     */
    private void rightRotate(RBNode y) {
        RBNode x = y.left;
        y.left = x.right;
        x.right.parent = y;
        x.parent = y.parent;
        if (y.parent == null) {
            root = x;
        } else {
            if (y == y.parent.left) {
                y.parent.left = x;
            } else {
                y.parent.right = x;
            }
        }
        x.right = y;
        y.parent = x;
    }

    /**
     * 红黑树插入方法
     * 
     * @param z
     */
    public void RBInsert(RBNode z) {
        if (root == null) {
            root = z;
            root.color = BLACK;
        } else {
            RBNode x = root;
            RBNode y = null;
            while (isNotNilNode(x)) {
                y = x;
                if (z.value.compareTo(x.value) &lt; 0) {
                    x = x.left;
                } else {
                    x = x.right;
                }
            }
            if (z.value.compareTo(y.value) &lt; 0) {
                y.left = z;
            } else {
                y.right = z;
            }
            z.color = RED;
            z.parent = y;
        }
        z.left = new RBNode(BLACK);
        z.right = new RBNode(BLACK);
        RBInsertFixUp(z);
    }

    /**
     * 解决插入冲突
     * 
     * @param z
     */
    private void RBInsertFixUp(RBNode z) {
        while (z.parent != null && z.parent.color.equals(RED)) {
            if (z.parent == z.parent.parent.left) {
                RBNode y = z.parent.parent.right;
                if (y.color.equals(RED)) {
                    z.parent.color = BLACK;
                    y.color = BLACK;
                    z.parent.parent.color = RED;
                    z = z.parent.parent;
                } else if (z == z.parent.right) {
                    z = z.parent;
                    leftRotate(z);
                } else if (z == z.parent.left) {
                    z.parent.color = BLACK;
                    z.parent.parent.color = RED;
                    rightRotate(z.parent.parent);
                }
            } else {
                RBNode y = z.parent.parent.left;
                if (y.color.equals(RED)) {
                    z.parent.color = BLACK;
                    y.color = BLACK;
                    z.parent.parent.color = RED;
                    z = z.parent.parent;
                } else if (z == z.parent.left) {
                    z = z.parent;
                    rightRotate(z);
                } else if (z == z.parent.right) {
                    z.parent.color = BLACK;
                    z.parent.parent.color = RED;
                    leftRotate(z.parent.parent);
                }
            }
        }
        root.color = BLACK;
    }

    /**
     * @param deleteNode
     */
    public void RBDelete(RBNode deleteNode) {
        RBNode y = null;
        RBNode z = serach(deleteNode.value);
        if (isNilNode(z.left) || isNilNode(z.right)) {
            y = z;
        } else {
            y = treeSuccessor(z);
        }
        RBNode x = null;
        if (isNotNilNode(y.left)) {
            x = y.left;
        } else {
            x = y.right;
        }
        x.parent = y.parent;
        if (isNilNode(y.parent)) {
            root = x;
        } else {
            if (y == y.parent.left) {
                y.parent.left = x;
            } else {
                y.parent.right = x;
            }
        }
        if (y != z) {
            z.value = y.value;
        }
        if (y.color.equals(BLACK)) {
            RBDeleteFixUp(x);
        }
    }

    /**
     * @param x
     */
    private void RBDeleteFixUp(RBNode x) {
        System.out.println("===="+x.value);
        // 解决黑黑冲突,完善中
        while (x != root && x.color.equals(BLACK)) {
            if (x == x.parent.left) {
                RBNode w = x.parent.right;
                if (w.color.equals(RED)) {
                    w.color = BLACK;
                    x.parent.color = RED;
                    leftRotate(x.parent);
                    w = x.parent.right;
                } else if (w.left.color.equals(BLACK) && w.right.color.equals(BLACK)) {
                    w.color = RED;
                    x = x.parent;
                } else if (w.right.color.equals(BLACK)) {
                    w.left.color = BLACK;
                    w.color = RED;
                    rightRotate(w);
                    w = x.parent.right;
                } else if (w.left.color.equals(BLACK)) {
                    w.color = x.parent.color;
                    x.parent.color = BLACK;
                    w.right.color = BLACK;
                    leftRotate(x.parent);
                    x = root;
                }
            } else {
                RBNode w = x.parent.left;
                if (w.color.equals(RED)) {
                    w.color = BLACK;
                    x.parent.color = RED;
                    rightRotate(x.parent);
                    w = x.parent.left;
                } else if (w.left.color.equals(BLACK) && w.right.color.equals(BLACK)) {
                    w.color = RED;
                    x = x.parent;
                } else if (w.left.color.equals(BLACK)) {
                    w.right.color = BLACK;
                    w.color = RED;
                    leftRotate(w);
                    w = x.parent.left;
                } else if (w.right.color.equals(BLACK)) {
                    w.color = x.parent.color;
                    x.parent.color = BLACK;
                    w.left.color = BLACK;
                    rightRotate(x.parent);
                    x = root;
                }
            }
        }
        x.color = BLACK;
    }

    /**
     * 找后继
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treeSuccessor(RBNode node) {
        if (node.right != null) {
            return treeMiniMum(node.right);
        }
        RBNode currentNode = getParentNode(node);
        while (currentNode != null && node == currentNode.right) {
            node = currentNode;
            currentNode = getParentNode(node);
        }
        return currentNode;
    }

    /**
     * 找前驱
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treePrecursor(RBNode node) {
        if (node.left != null) {
            return treeMaxiMum(node.left);
        }
        RBNode currentNode = getParentNode(node);
        while (currentNode != null && node == currentNode.left) {
            node = currentNode;
            currentNode = getParentNode(node);
        }
        return currentNode;
    }

    /**
     * 最大节点
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treeMaxiMum(RBNode node) {
        while (isNotNilNode(node.right)) {
            node = node.right;
        }
        return node;
    }

    /**
     * 最小节点
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treeMiniMum(RBNode node) {
        while (isNotNilNode(node.left)) {
            node = node.left;
        }
        return node;
    }

    /**
     * 找节点的父节点
     * 
     * @param node
     * @return TreeNode
     */
    public RBNode getParentNode(RBNode node) {
        RBNode current = root;
        RBNode trailCurrent = null;
        while (isNotNilNode(current)) {
            if (current.value.compareTo(node.value) == 0) {
                break;
            }
            trailCurrent = current;
            if (node.value.compareTo(current.value) &lt; 0) {
                current = current.left;
            } else {
                current = current.right;
            }
        }
        return trailCurrent;
    }

    /**
     * 搜索
     * 
     * @param value
     * @return TreeNode
     */
    public RBNode serach(RBValue value) {
        return treeSerach(root, value);
    }

    /**
     * 搜索
     * 
     * @param node
     * @param value
     * @return TreeNode
     */
    public RBNode treeSerach(RBNode node, RBValue value) {
        if (isNotNilNode(node) && node.value.compareTo(value) == 0) {
            return node;
        }
        if (value.compareTo(node.value) &lt; 0) {
            return treeSerach(node.left, value);
        } else {
            return treeSerach(node.right, value);
        }
    }

    /**
     * 中序遍历
     * 
     * @param node
     */
    public void inOrder(RBNode node) {
        if (isNotNilNode(node)) {
            inOrder(node.left);
            System.out.println(node.value+","+node.color);
            inOrder(node.right);
        }
    }
    
    /**
     * 先序遍历
     * 
     * @param node
     */
    public void perOrder(RBNode node) {
        if (isNotNilNode(node)) {
            System.out.println(node.value+","+node.color);
            perOrder(node.left);
            perOrder(node.right);
        }
    }

    /**
     * @param node
     * @return 是否为NIL[T]节点
     */
    private boolean isNotNilNode(RBNode node) {
        return node != null && node.value != null;
    }

    /**
     * @param node
     * @return 是否为NIL[T]节点
     */
    private boolean isNilNode(RBNode node) {
        return !isNotNilNode(node);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        RBTree tree = new RBTree();
        
        
        tree.RBInsert(new RBNode(new RBValue(3)));
        tree.RBInsert(new RBNode(new RBValue(4)));
        tree.RBInsert(new RBNode(new RBValue(12)));
        tree.RBInsert(new RBNode(new RBValue(13)));
        tree.RBInsert(new RBNode(new RBValue(11)));
        tree.RBInsert(new RBNode(new RBValue(15)));
        tree.RBDelete(new RBNode(new RBValue(12)));
        System.out.println("=================");
        System.out.println("root = "+tree.root.value);
        System.out.println("=================");
        tree.inOrder(tree.root);
        System.out.println("=================");
        tree.perOrder(tree.root);
    }

}
</pre><br /><pre name="code" class="java">
package acmcode;

/**
 * @author Leon.Chen
 *
 */
public class RBNode {

    public RBNode parent;

    public RBNode left;

    public RBNode right;

    public RBValue value;

    public String color;

    public RBNode(String color) {
        this.color = color;
    }

    public RBNode() {

    }

    public RBNode(RBValue value) {
        this.value = value;
    }

}
</pre><br /><pre name="code" class="java">
package acmcode;

public class RBValue {

    public int value;

    public RBValue(int value) {
        this.value = value;
    }

    public int compareTo(RBValue otherValue) {
        int thisVal = this.value;
        int anotherVal = otherValue.value;
        return (thisVal &lt; anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
    }

    public String toString() {
        return new Integer(value).toString();
    }
}
</pre><br />忘了附图
          <br/>
          <span style="color:red;">
            <a href="http://leon-a.javaeye.com/blog/215494#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 16 Jul 2008 17:20:46 +0800</pubDate>
        <link>http://leon-a.javaeye.com/blog/215494</link>
        <guid>http://leon-a.javaeye.com/blog/215494</guid>
      </item>
      <item>
        <title>四则运算的中缀转后缀，逆波兰表达式求值</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://leon-a.javaeye.com/blog/186104" style="color:red;">http://leon-a.javaeye.com/blog/186104</a>&nbsp;
          发表时间: 2008年04月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          首先描述问题<br /><pre name="code" class="java">
给定一个字符串
example:"4-(4-3*5+(2*4)+100)/10";
要求输出结果"-5.70";结果四舍五入，保留两位小数
</pre><br />首先进行的是括号优先级的处理<br /><pre name="code" class="java">
	public BigDecimal calculateString(String str) {
		char[] strs = str.toCharArray();
		Stack&lt;String> stack = new Stack&lt;String>();

		for (int i = 0; i &lt; strs.length; i++) {
			String stackStr = String.valueOf(strs[i]);
			stack.push(stackStr);
			if (")".equals(stack.top())) {
				String subStr = null;
				while (!"(".equals(stack.top())) {
					stack.pop();
					if (!"(".equals(stack.top())) {
						subStr = addEnd(subStr, stack.top());
					}
				}
				String pushStr = CalculateReversePolishExpression(subStr);
				stack.pop();
				stack.push(pushStr);
			}

		}
		String resultStr = null;
		while (stack.count != 0) {
			resultStr = CalculateReversePolishExpression(stack.toString());
		}
		BigDecimal result = null;
		if (resultStr != null) {
			result = new BigDecimal(resultStr);
		} else {
			result = BigDecimal.ZERO;
		}
		return result.setScale(2, BigDecimal.ROUND_HALF_UP);
	}
</pre><br />将每个字符逐一进栈，当扫描到")"时，进行出栈操作，直到栈顶元素等于"("<br />并记录出栈的"("与")"之间的字符串为subStr<br />然后是对subStr求后缀表达式，并计算结果<br />也就是这句代码<br /><pre name="code" class="java">
String pushStr = CalculateReversePolishExpression(subStr);
</pre><br />再把结果进栈<br />最后stack的内容是去掉括号的一个四则表达式<br />再进行一次CalculateReversePolishExpression方法，则得到最终结果<br /><br />中缀转后缀表达式的基本思路<br />基本思路如下：<br />用一个链表 List&lt;String> 储存将要生成的后缀表达式<br />用一个栈 Stack&lt;String> 储存操作符<br />判断当前节点， 如果是操作数， 直接加入后缀表达式中， 如果是操作符，则比较前一个操作符和当前操作符的优先级，<br />如果前一个操作符优先级较高，则将前一个操作符加入后缀表达式中，否则将操作符压入操作符栈，如果遇到反括号 ')', 则在操作符栈中反向搜索，直到遇到匹配的正括号为止，将中间的操作符依次加到后缀表达式中。<br /><br />然后是后缀表达式的计算<br /><br />遍历储存后缀表达式的链表，将元素依次进栈，当遇到操作符时，连续出栈两个元素，进行运算，再将结果进栈，最后栈内留下的元素就是计算结果<br /><br />最后再贴出茫茫多的代码<br /><pre name="code" class="java">
package graph;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 
 * 应用：逆波兰表达式
 * 
 * @author Leon.Chen
 * 
 */
public class CalculateString {

	public BigDecimal calculateString(String str) {
		char[] strs = str.toCharArray();
		Stack&lt;String> stack = new Stack&lt;String>();

		for (int i = 0; i &lt; strs.length; i++) {
			String stackStr = String.valueOf(strs[i]);
			stack.push(stackStr);
			if (")".equals(stack.top())) {
				String subStr = null;
				while (!"(".equals(stack.top())) {
					stack.pop();
					if (!"(".equals(stack.top())) {
						subStr = addEnd(subStr, stack.top());
					}
				}
				String pushStr = CalculateReversePolishExpression(subStr);
				stack.pop();
				stack.push(pushStr);
			}

		}
		String resultStr = null;
		while (stack.count != 0) {
			resultStr = CalculateReversePolishExpression(stack.toString());
		}
		BigDecimal result = null;
		if (resultStr != null) {
			result = new BigDecimal(resultStr);
		} else {
			result = BigDecimal.ZERO;
		}
		return result.setScale(2, BigDecimal.ROUND_HALF_UP);
	}

	public String[] matcher(String regex, String str) {
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(str);
		List&lt;String> list = new ArrayList&lt;String>();
		while (matcher.find()) {
			list.add(matcher.group());
		}
		String[] result = new String[list.size()];
		return list.toArray(result);
	}

	public List&lt;String> createReversePolishExpression(String subStr) {
		String regex = "\\d+\\.{0,1}\\d*";
		String[] numbers = matcher(regex, subStr);
		String changeStr = subStr.replaceAll(regex, "0").replaceAll("\\-\\-0",
				"-1").replaceAll("\\+\\-0", "+1").replaceAll("\\*\\-0", "*1")
				.replaceAll("\\/\\-0", "/1");
		char[] chars = changeStr.toCharArray();
		int index = 0;
		List&lt;String> list = new ArrayList&lt;String>();
		for (int i = 0; i &lt; chars.length; i++) {
			String str = String.valueOf(chars[i]);
			if ("0".equals(str)) {
				list.add(numbers[index++]);
			} else if ("1".equals(str)) {
				list.add("-" + numbers[index++]);
			} else {
				list.add(str);
			}
		}
		List&lt;String> suffix = new ArrayList&lt;String>();
		Stack&lt;String> operator = new Stack&lt;String>();
		for (int i = 0; i &lt; list.size(); i++) {
			if (!isOperatorType(list.get(i))) {
				suffix.add(list.get(i));
			} else {
				if (operator.count == 0) {
					operator.push(list.get(i));
				} else {
					while (operator.count != 0&&compare(operator.top(), list.get(i)) >= 0) {
						String top = operator.top();
						operator.pop();
						suffix.add(top);
					} 
					operator.push(list.get(i));

				}
			}
		}

		while (operator.count != 0) {
			suffix.add(operator.top());
			operator.pop();
		}
		return suffix;
	}

	public String CalculateReversePolishExpression(String subStr) {
		List&lt;String> suffix = createReversePolishExpression(subStr);
		Stack&lt;Double> stack = new Stack&lt;Double>();
		for (int i = 0; i &lt; suffix.size(); i++) {
			if (!isOperatorType(suffix.get(i))) {
				stack.push(Double.valueOf(suffix.get(i)));
			} else {
				Double current = stack.top();
				stack.pop();
				Double previous = null;
				if (stack.count != 0) {
					previous = stack.top();
					stack.pop();
				} else {
					previous = new Double(0);
				}
				Double result = calculate(suffix.get(i), previous, current);
				stack.push(result);
			}
		}
		return stack.top().toString();
	}

	public String addEnd(String str, String a) {
		StringBuffer buf = new StringBuffer();
		buf.append(a);
		if (str != null) {
			buf.append(str);
		}
		return buf.toString();
	}

	public boolean isOperatorType(String str) {
		if (str.equals("+") || str.equals("-") || str.equals("*")
				|| str.equals("/")) {
			return true;
		}
		return false;
	}

	public int compare(String op1, String op2) {
		Integer iop1 = getOperator(op1);
		Integer iop2 = getOperator(op2);
		return iop1.compareTo(iop2);
	}

	public Integer getOperator(String op) {
		if ("+".equals(op) || "-".equals(op)) {
			return new Integer(0);
		}
		if ("*".equals(op) || "/".equals(op)) {
			return new Integer(1);
		}
		return null;
	}

	public Double calculate(String op, Double previous, Double current) {
		if ("+".equals(op)) {
			return previous + current;
		}
		if ("-".equals(op)) {
			return previous - current;
		}
		if ("*".equals(op)) {
			return previous * current;
		}
		if ("/".equals(op)) {
			return previous / current;
		}
		return null;
	}

	public static void main(String[] args) {
		String[] strs = new String[]{"(5+6)*7","(-1)/(-3)","1/(-3)","-1/7","7+(3*5)-(8+20/2)","4-(4-3*5+(2*4)+100)/10"};
		for(int i=0;i&lt;strs.length;i++){
			BigDecimal result = new CalculateString().calculateString(strs[i]);
			System.out.println(result.toString());
		}
		
	}

}

</pre><br />自己写的stack<br /><br /><pre name="code" class="java">
package graph;

public class Stack&lt;T> {
	public StackNode&lt;T> stackTop;
	public int count;
	public void push(T info) {
		StackNode&lt;T> node = new StackNode&lt;T>();
		node.info = info;
		node.link = stackTop;
		stackTop = node;
		count++;
	} 
	
	public void pop() {
		if(stackTop == null) {
			System.out.println("null stack");
		} else {
			stackTop = stackTop.link;
			count--;
		}

	}
	
	public boolean isEmpty() {
		return count == 0;
	}
	
	public T top() {
		if(stackTop == null) {
			return null;
		}
		return stackTop.info;
	}
	
	public String toString(){
		Stack&lt;T> other = new Stack&lt;T>();
		while(count != 0){
			T top = top();
			pop();
			other.push(top);
		}
		StringBuffer buf = new StringBuffer();
		while(other.count !=0){
			buf.append(other.top());
			other.pop();
		}
		return buf.toString();
	}

}

</pre><br />stack节点<br /><pre name="code" class="java">
package graph;

public class StackNode&lt;T> {
	public StackNode&lt;T> link;
	public T info;
}

</pre><br /><br />懒得copy的话下载附件
          <br/>
          <span style="color:red;">
            <a href="http://leon-a.javaeye.com/blog/186104#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 23 Apr 2008 23:10:37 +0800</pubDate>
        <link>http://leon-a.javaeye.com/blog/186104</link>
        <guid>http://leon-a.javaeye.com/blog/186104</guid>
      </item>
      <item>
        <title>最大0，1子矩阵</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://leon-a.javaeye.com/blog/184635" style="color:red;">http://leon-a.javaeye.com/blog/184635</a>&nbsp;
          发表时间: 2008年04月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          首先描述一下问题<br /><pre name="code" class="java">
 /**
 * 
 * 时间限制(普通/Java):6000MS/20000MS 运行内存限制:65536KByte
 * 总提交:131 测试通过:32
 * 描述
 * 在一个0,1方阵中找出其中最大的全0子矩阵，所谓最大是指O的个数最多
 * 输入
 * 单组数据第一行为整数N，其中1&lt;=N&lt;=2000，为方阵的大小，紧接着N行每行均有N个0或1，相邻两数间严格用一个空格隔开
 * 输出
 * 输出仅一行包含一个整数表示要求的最大的全零子矩阵中零的个数
 * 样例输入
 * 5
 * 0 1 0 1 0
 * 0 0 0 0 0
 * 0 0 0 0 1
 * 1 0 0 0 0
 * 0 1 0 0 0
 * 样例输出
 * 9
 */
</pre><br />我的做法是遍历每个点，根据每个点横向和纵向的构造全0矩阵，选取最大的全0矩阵输出<br />正确性应该是没问题的，不过时间复杂度<br />遍历的复杂度是o(n^2)然后每个点构造矩形复杂度也是o(n^2)<br />最大时间复杂度就为n^4<br />因此求优化<img src="/images/smiles/icon_arrow.gif"/><br /><pre name="code" class="java">
package graph;
/**
 * 
 * 时间限制(普通/Java):6000MS/20000MS 运行内存限制:65536KByte
 * 总提交:131 测试通过:32
 * 描述
 * 在一个0,1方阵中找出其中最大的全0子矩阵，所谓最大是指O的个数最多
 * 输入
 * 单组数据第一行为整数N，其中1&lt;=N&lt;=2000，为方阵的大小，紧接着N行每行均有N个0或1，相邻两数间严格用一个空格隔开
 * 输出
 * 输出仅一行包含一个整数表示要求的最大的全零子矩阵中零的个数
 * 样例输入
 * 5
 * 0 1 0 1 0
 * 0 0 0 0 0
 * 0 0 0 0 1
 * 1 0 0 0 0
 * 0 1 0 0 0
 * 样例输出
 * 9
 * 
 * @author Leon.Chen
 *
 */
public class AllZeroMatrix {
	/**
	 * 输入矩阵
	 */
	public int[][] matrix;
	/**
	 * 矩阵最大行
	 */
	public int maxRow;
	/**
	 * 矩阵最大列
	 */
	public int maxColumn;
	/**
	 * 被乘数
	 */
	public int multiplicand;
	/**
	 * 最大全零矩阵
	 */
	public int totalCount;

	/**
	 * 每个点向下，向右扩张矩形，取最大的矩形
	 * 
	 * @param row
	 * @param column
	 */
	public void spread(int row, int column) {
		int rowStart = row;
		int rowEnd = row;
		while (rowEnd &lt; maxRow) {
			if (matrix[rowEnd][column] == 0) {
				rowEnd++;
			} else {
				break;
			}
		}
		this.multiplicand = 0;
		spreadMatrixRight(rowStart, rowEnd, column);
		int count = (rowEnd - rowStart) * multiplicand;
		if (totalCount &lt; count) {
			totalCount = count;
		}
		int columnStart = column;
		int columnEnd = column;
		while (columnEnd &lt; maxColumn) {
			if (matrix[row][columnEnd] == 0) {
				columnEnd++;
			} else {
				break;
			}
		}
		this.multiplicand = 0;
		spreadMatrixbelow(columnStart, columnEnd, row);
		count = (columnEnd - columnStart) * multiplicand;
		if (totalCount &lt; count) {
			totalCount = count;
		}
	}

	/**
	 * 矩阵的向右扩张
	 * 
	 * @param start
	 * @param end
	 * @param column
	 */

	public void spreadMatrixRight(int start, int end, int column) {
		boolean flg = true;
		for (int i = start; i &lt; end; i++) {
			if (matrix[i][column] == 1) {
				flg = false;
				break;
			}
		}
		if (flg) {
			multiplicand++;
			int nextColumn = column;
			nextColumn++;
			if (nextColumn &lt; maxColumn) {
				spreadMatrixRight(start, end, nextColumn);
			}
		}
	}

	/**
	 * 矩阵的向下扩张
	 * 
	 * @param start
	 * @param end
	 * @param row
	 */
	public void spreadMatrixbelow(int start, int end, int row) {
		boolean flg = true;
		for (int i = start; i &lt; end; i++) {
			if (matrix[row][i] == 1) {
				flg = false;
				break;
			}
		}
		if (flg) {
			multiplicand++;
			int nextRow = row;
			nextRow++;
			if (nextRow &lt; maxRow) {
				spreadMatrixbelow(start, end, nextRow);
			}
		}
	}

	/**
	 * 得到最大全零矩阵的大小
	 * 
	 * @param printMatrix
	 */
	public void getAllZeroMatrix(int[][] printMatrix) {
		matrix = printMatrix;
		maxRow = matrix.length;
		maxColumn = matrix[0].length;
		for (int i = 0; i &lt; maxRow; i++) {
			for (int j = 0; j &lt; maxColumn; j++) {
				int count = (maxRow - i) * (maxColumn - j);
				if (count &lt;= totalCount) {
					continue;
				}
				if (matrix[i][j] != 1) {
					spread(i, j);
				}
			}
		}
		System.out.println(totalCount);
	}
	
	public static void main(String[] args) {
		int[][] printMatrix = new int[][]{
				{0,1,0,1,0},
				{0,0,0,0,0},
				{0,0,0,0,1},
				{1,0,0,0,0},
				{0,1,0,0,0},
		};
		long start = System.currentTimeMillis();
		new AllZeroMatrix().getAllZeroMatrix(printMatrix);
		long end = System.currentTimeMillis();
		System.out.println((end-start)+"ms");
	}
}

</pre>
          <br/>
          <span style="color:red;">
            <a href="http://leon-a.javaeye.com/blog/184635#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 20 Apr 2008 21:16:47 +0800</pubDate>
        <link>http://leon-a.javaeye.com/blog/184635</link>
        <guid>http://leon-a.javaeye.com/blog/184635</guid>
      </item>
      <item>
        <title>数据挖掘 决策树ID3算法原理</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://leon-a.javaeye.com/blog/181958" style="color:red;">http://leon-a.javaeye.com/blog/181958</a>&nbsp;
          发表时间: 2008年04月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          上一篇博客写了ID3算法的简单实现<br />这一篇讲讲ID3的原理<br />写这个算法是由于某同事的同学的毕业设计，关系够复杂的了==|||，写完这个算法，突然对数据挖掘有了兴趣，决定把C4.5,C5.0算法也一并实现，并且再研究一下数据挖掘的分类算法<br />其实这篇原理，没有我自己的内容。。。引用某人blog的东东吧（我本人倒是很反感抄袭的）<br />首先奉上blog作者：神威异度<br />虽然未曾与之交谈，不过经历千辛万苦的搜索之后，终于在他的blog发现了有价值的东西（这里要提一下，想要在国内搜索出有价值的东西真不容易，到处充斥着转载，小小鄙视一下我自己先），在这里万分感谢神威异度同学<br />奉上blog链接：http://www.blog.edu.cn/user2/huangbo929/archives/2006/1533249.shtml<br />再不厌其烦的把人家的东西copy到我这里。<br /><br />决策树生成原理<br />Abstract <br />This paper details the ID3 classification algorithm. Very simply, ID3 builds a decision tree from a fixed set of examples. The resulting tree is used to classify future samples. The example has several attributes and belongs to a class (like yes or no). The leaf nodes of the decision tree contain the class name whereas a non-leaf node is a decision node. The decision node is an attribute test with each branch (to another decision tree) being a possible value of the attribute. ID3 uses information gain to help it decide which attribute goes into a decision node. The advantage of learning a decision tree is that a program, rather than a knowledge engineer, elicits knowledge from an expert.<br /><br />Introduction <br />J. Ross Quinlan originally developed ID3 at the University of Sydney. He first presented ID3 in 1975 in a book, Machine Learning, vol. 1, no. 1. ID3 is based off the Concept Learning System (CLS) algorithm. The basic CLS algorithm over a set of training instances C:<br /><br />Step 1: If all instances in C are positive, then create YES node and halt.<br /><br />If all instances in C are negative, create a NO node and halt.<br /><br />Otherwise select a feature, F with values v1, ..., vn and create a decision node.<br /><br />Step 2: Partition the training instances in C into subsets C1, C2, ..., Cn according to the values of V.<br /><br />Step 3: apply the algorithm recursively to each of the sets Ci.<br /><br />Note, the trainer (the expert) decides which feature to select.<br /><br />ID3 improves on CLS by adding a feature selection heuristic. ID3 searches through the attributes of the training instances and extracts the attribute that best separates the given examples. If the attribute perfectly classifies the training sets then ID3 stops; otherwise it recursively operates on the n (where n = number of possible values of an attribute) partitioned subsets to get their "best" attribute. The algorithm uses a greedy search, that is, it picks the best attribute and never looks back to reconsider earlier choices.<br /><br />Discussion <br />ID3 is a nonincremental algorithm, meaning it derives its classes from a fixed set of training instances. An incremental algorithm revises the current concept definition, if necessary, with a new sample. The classes created by ID3 are inductive, that is, given a small set of training instances, the specific classes created by ID3 are expected to work for all future instances. The distribution of the unknowns must be the same as the test cases. Induction classes cannot be proven to work in every case since they may classify an infinite number of instances. Note that ID3 (or any inductive algorithm) may misclassify data.<br /><br />Data Description <br /> <br /><br />The sample data used by ID3 has certain requirements, which are:<br /><br />Attribute-value description - the same attributes must describe each example and have a fixed number of values. <br />Predefined classes - an example's attributes must already be defined, that is, they are not learned by ID3. <br />Discrete classes - classes must be sharply delineated. Continuous classes broken up into vague categories such as a metal being "hard, quite hard, flexible, soft, quite soft" are suspect. <br />Sufficient examples - since inductive generalization is used (i.e. not provable) there must be enough test cases to distinguish valid patterns from chance occurrences. <br />Attribute Selection <br /> <br /><br />How does ID3 decide which attribute is the best? A statistical property, called information gain, is used. Gain measures how well a given attribute separates training examples into targeted classes. The one with the highest information (information being the most useful for classification) is selected. In order to define gain, we first borrow an idea from information theory called entropy. Entropy measures the amount of information in an attribute. <br /><br />Given a collection S of c outcomes<br /><br /> <br /><br />Entropy(S) = S -p(I) log2 p(I) <br /> <br /><br />where p(I) is the proportion of S belonging to class I. S is over c. Log2 is log base 2.<br /><br />Note that S is not an attribute but the entire sample set.<br /><br />Example 1 <br /> <br /><br />If S is a collection of 14 examples with 9 YES and 5 NO examples then<br /><br /> <br /><br />Entropy(S) = - (9/14) Log2 (9/14) - (5/14) Log2 (5/14) = 0.940 <br /> <br /><br />Notice entropy is 0 if all members of S belong to the same class (the data is perfectly classified). The range of entropy is 0 ("perfectly classified") to 1 ("totally random").<br /><br />Gain(S, A) is information gain of example set S on attribute A is defined as<br /><br /> <br /><br />Gain(S, A) = Entropy(S) - S ((|Sv| / |S|) * Entropy(Sv)) <br /> <br /><br />Where:<br /><br />S is each value v of all possible values of attribute A<br /><br />Sv = subset of S for which attribute A has value v<br /><br />|Sv| = number of elements in Sv <br /><br />|S| = number of elements in S<br /><br />Example 2 <br /> <br /><br />Suppose S is a set of 14 examples in which one of the attributes is wind speed. The values of Wind can be Weak or Strong. The classification of these 14 examples are 9 YES and 5 NO. For attribute Wind, suppose there are 8 occurrences of Wind = Weak and 6 occurrences of Wind = Strong. For Wind = Weak, 6 of the examples are YES and 2 are NO. For Wind = Strong, 3 are YES and 3 are NO. Therefore<br /><br /> <br /><br />Gain(S,Wind)=Entropy(S)-(8/14)*Entropy(Sweak)-(6/14)*Entropy(Sstrong) <br /> <br /><br />= 0.940 - (8/14)*0.811 - (6/14)*1.00 <br /><br />= 0.048 <br /><br />Entropy(Sweak) = - (6/8)*log2(6/8) - (2/8)*log2(2/8) = 0.811<br /><br />Entropy(Sstrong) = - (3/6)*log2(3/6) - (3/6)*log2(3/6) = 1.00<br /><br />For each attribute, the gain is calculated and the highest gain is used in the decision node.<br /><br />Example of ID3 <br /> <br /><br />Suppose we want ID3 to decide whether the weather is amenable to playing baseball. Over the course of 2 weeks, data is collected to help ID3 build a decision tree (see table 1).<br /><br />The target classification is "should we play baseball?" which can be yes or no.<br /><br />The weather attributes are outlook, temperature, humidity, and wind speed. They can have the following values:<br /><br />outlook = { sunny, overcast, rain }<br /><br />temperature = {hot, mild, cool }<br /><br />humidity = { high, normal }<br /><br />wind = {weak, strong }<br /><br />Examples of set S are:<br /><br />Day Outlook Temperature Humidity Wind Play ball <br />D1 Sunny  Hot High  Weak No  <br />D2 Sunny  Hot High  Strong No  <br />D3 Overcast  Hot High  Weak Yes  <br />D4 Rain  Mild High  Weak Yes  <br />D5 Rain  Cool Normal  Weak Yes  <br />D6 Rain  Cool Normal  Strong No  <br />D7 Overcast  Cool Normal  Strong Yes  <br />D8 Sunny  Mild High  Weak No  <br />D9 Sunny  Cool Normal  Weak Yes  <br />D10 Rain  Mild Normal  Weak Yes  <br />D11 Sunny  Mild Normal  Strong Yes  <br />D12 Overcast  Mild High  Strong Yes  <br />D13 Overcast  Hot Normal  Weak Yes  <br />D14 Rain  Mild High  Strong No  <br /><br /><br /><br /> <br /><br />Table 1 <br /> <br /><br />We need to find which attribute will be the root node in our decision tree. The gain is calculated for all four attributes:<br /><br />Gain(S, Outlook) = 0.246<br /><br />Gain(S, Temperature) = 0.029<br /><br />Gain(S, Humidity) = 0.151<br /><br />Gain(S, Wind) = 0.048 (calculated in example 2)<br /><br />Outlook attribute has the highest gain, therefore it is used as the decision attribute in the root node.<br /><br />Since Outlook has three possible values, the root node has three branches (sunny, overcast, rain). The next question is "what attribute should be tested at the Sunny branch node?" Since we=92ve used Outlook at the root, we only decide on the remaining three attributes: Humidity, Temperature, or Wind.<br /><br />Ssunny = {D1, D2, D8, D9, D11} = 5 examples from table 1 with outlook = sunny<br /><br />Gain(Ssunny, Humidity) = 0.970<br /><br />Gain(Ssunny, Temperature) = 0.570<br /><br />Gain(Ssunny, Wind) = 0.019<br /><br />Humidity has the highest gain; therefore, it is used as the decision node. This process goes on until all data is classified perfectly or we run out of attributes.<br /><br />The final decision = tree<br /><br />The decision tree can also be expressed in rule format:<br /><br />IF outlook = sunny AND humidity = high THEN playball = no<br /><br />IF outlook = rain AND humidity = high THEN playball = no<br /><br />IF outlook = rain AND wind = strong THEN playball = yes<br /><br />IF outlook = overcast THEN playball = yes<br /><br />IF outlook = rain AND wind = weak THEN playball = yes<br /><br />ID3 has been incorporated in a number of commercial rule-induction packages. Some specific applications include medical diagnosis, credit risk assessment of loan applications, equipment malfunctions by their cause, classification of soybean diseases, and web search classification.<br /><br />Conclusion <br />The discussion and examples given show that ID3 is easy to use. Its primary use is replacing the expert who would normally build a classification tree by hand. As industry has shown, ID3 has been effective.
          <br/>
          <span style="color:red;">
            <a href="http://leon-a.javaeye.com/blog/181958#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 11 Apr 2008 22:24:36 +0800</pubDate>
        <link>http://leon-a.javaeye.com/blog/181958</link>
        <guid>http://leon-a.javaeye.com/blog/181958</guid>
      </item>
      <item>
        <title>决策树ID3算法</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://leon-a.javaeye.com/blog/178585" style="color:red;">http://leon-a.javaeye.com/blog/178585</a>&nbsp;
          发表时间: 2008年04月01日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
package graph;      
     
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;      
     
/**      
 * 决策树的ID3算法      
 * 参照实现http://www.blog.edu.cn/user2/huangbo929/archives/2006/1533249.shtml    
 * @author Leon.Chen      
 */     
public class DTree {      
          
    /**    
     * root    
     */     
    TreeNode root;      
          
    /**    
     * 可见性数组    
     */     
    private static boolean[] visable;      
          
    private Object[] array;  
    
    private int index;
     
    /**    
     * @param args    
     */     
    @SuppressWarnings("boxing")      
    public static void main(String[] args) {      
        //初始数据      
        Object[] array = new Object[] {       
                        new String[]{ "Sunny"    ,"Hot"   ,"High"    ,"Weak"    ,"No" },      
                        new String[]{ "Sunny"    ,"Hot"   ,"High"    ,"Strong"  ,"No" },      
                        new String[]{ "Overcast" ,"Hot"   ,"High"    ,"Weak"    ,"Yes"},      
                        new String[]{ "Rain"     ,"Mild"  ,"High"    ,"Weak"    ,"Yes"},      
                        new String[]{ "Rain"     ,"Cool"  ,"Normal"  ,"Weak"    ,"Yes"},      
                        new String[]{ "Rain"     ,"Cool"  ,"Normal"  ,"Strong"  ,"No" },      
                        new String[]{ "Overcast" ,"Cool"  ,"Normal"  ,"Strong"  ,"Yes"},      
                        new String[]{ "Sunny"    ,"Mild"  ,"High"    ,"Weak"    ,"No" },      
                        new String[]{ "Sunny"    ,"Cool"  ,"Normal"  ,"Weak"    ,"Yes"},      
                        new String[]{ "Rain"     ,"Mild"  ,"Normal"  ,"Weak"    ,"Yes"},      
                        new String[]{ "Sunny"    ,"Mild"  ,"Normal"  ,"Strong"  ,"Yes"},      
                        new String[]{ "Overcast" ,"Mild"  ,"High"    ,"Strong"  ,"Yes"},      
                        new String[]{ "Overcast" ,"Hot"   ,"Normal"  ,"Weak"    ,"Yes"},      
                        new String[]{ "Rain"     ,"Mild"  ,"High"    ,"Strong"  ,"No" },      
                        };      
              
        DTree tree = new DTree();       
        tree.create(array,4);
    } 
    
    public void create(Object[] array,int index){
    	this.array = array;
    	init(array,index);
    	createDTree(array);
    	printDTree(root);
    }
       
    public Object[] getMaxGain(Object[] array){   
        Object[] result = new Object[2];   
        double gain = 0;   
        int index = 0;
        
        for(int i=0;i&lt;visable.length;i++){   
            if(!visable[i]){   
                double value = gain(array,i);   
                if(gain &lt; value){   
                    gain = value;   
                    index = i;   
                }   
            }   
        }   
        result[0] = gain;   
        result[1] = index;   
        visable[index] = true;   
        return result;   
    }   
       
    public void createDTree(Object[] array) {   
        Object[] maxgain = getMaxGain(array);   
        if (root == null) {   
            root = new TreeNode();   
            root.parent = null;   
            root.parentArrtibute = null;   
            root.arrtibutes = getArrtibutes(((Integer) maxgain[1]).intValue());   
            root.nodeName = getNodeName(((Integer) maxgain[1]).intValue());  
            root.childNodes = new TreeNode[root.arrtibutes.length];
            insertTree(array,root);
        }
    }   
       
    public void insertTree(Object[] array,TreeNode parentNode){
    	String[] arrtibutes = parentNode.arrtibutes;
    	for(int i=0;i&lt;arrtibutes.length;i++){
    		Object[] pickArray = pickUpAndCreateArray(array,arrtibutes[i],getNodeIndex(parentNode.nodeName));
    		Object[] info = getMaxGain(pickArray);
    		double gain = ((Double)info[0]).doubleValue();
    		if(gain != 0){
    			int index = ((Integer) info[1]).intValue();
    			System.out.println("gain = "+gain+" ,node name = "+getNodeName(index));
        		TreeNode currentNode = new TreeNode();
        		currentNode.parent = parentNode;
        		currentNode.parentArrtibute = arrtibutes[i];
        		currentNode.arrtibutes = getArrtibutes(index);
        		currentNode.nodeName = getNodeName(index);
        		currentNode.childNodes = new TreeNode[currentNode.arrtibutes.length];
        		parentNode.childNodes[i] = currentNode;
        		insertTree(pickArray,currentNode);
    		}else {
    			TreeNode leafNode = new TreeNode();
    			leafNode.parent = parentNode;
    			leafNode.parentArrtibute = arrtibutes[i];
    			leafNode.arrtibutes = new String[0];
    			leafNode.nodeName = getLeafNodeName(pickArray);
    			leafNode.childNodes = new TreeNode[0];
    			parentNode.childNodes[i] = leafNode;
    		}
    	}

    }
    
    public void printDTree(TreeNode node){
    	System.out.println(node.nodeName);

    	TreeNode[] childs = node.childNodes;
    	for(int i=0;i&lt;childs.length;i++){
    		if(childs[i]!=null){
    			System.out.println(childs[i].parentArrtibute);
    			printDTree(childs[i]);
    		}
    	}
    }
  
    /**      
     * @param dataArray 原始数组 D     
     * @param criterion 标准值      
     * @return double      
     */     
    public void init(Object[] dataArray,int index) {
    	this.index = index;
        //数据初始化   
        visable = new boolean[((String[])dataArray[0]).length];      
        for(int i=0;i&lt;visable.length;i++) {    
            if(i == index){   
                visable[i] = true;    
            }else {   
                visable[i] = false;    
            }   
        }   
    }   
    
    public Object[] pickUpAndCreateArray(Object[] array,String arrtibute,int index){
    	List&lt;String[]> list = new ArrayList&lt;String[]>();
    	for(int i=0;i&lt;array.length;i++){
    		String[] strs = (String[])array[i];
    		if(strs[index].equals(arrtibute)){
    			list.add(strs);
    		}
    	}
    	return list.toArray();
    }
  
    /**    
     * Entropy(S)    
     * @param array    
     * @return double     
     */     
    public double gain(Object[] array,int index) {      
        String[] playBalls = getArrtibutes(this.index);   
        int[] counts = new int[playBalls.length];      
        for(int i=0;i&lt;counts.length;i++) {   
            counts[i] = 0;      
        }   
        for(int i=0;i&lt;array.length;i++) {   
            String[] strs = (String[])array[i];   
            for(int j=0;j&lt;playBalls.length;j++) {   
                if(strs[this.index].equals(playBalls[j])) {   
                    counts[j]++;   
                }   
            }   
        }   
        /**  
         * Entropy(S) = S -p(I) log2 p(I)  
         */  
        double entropyS = 0;   
        for(int i=0;i&lt;counts.length;i++) {      
            entropyS += DTreeUtil.sigma(counts[i],array.length);      
        }   
        String[] arrtibutes = getArrtibutes(index);   
        /**  
         * total ((|Sv| / |S|) * Entropy(Sv))   
         */  
        double sv_total = 0;   
        for(int i=0;i&lt;arrtibutes.length;i++){   
            sv_total += entropySv(array, index,arrtibutes[i],array.length);   
        }   
        return entropyS-sv_total;   
    }   
       
    /**  
     * ((|Sv| / |S|) * Entropy(Sv))  
     * @param array  
     * @param index  
     * @param arrtibute  
     * @param allTotal  
     * @return  
     */  
    public double entropySv(Object[] array,int index,String arrtibute,int allTotal) {   
        String[] playBalls = getArrtibutes(this.index);   
        int[] counts = new int[playBalls.length];   
        for(int i=0;i&lt;counts.length;i++) {   
            counts[i] = 0;      
        }   
  
        for (int i = 0; i &lt; array.length; i++) {   
            String[] strs = (String[]) array[i];   
            if (strs[index].equals(arrtibute)) {   
                for (int k = 0; k &lt; playBalls.length; k++) {   
                    if (strs[this.index].equals(playBalls[k])) {   
                        counts[k]++;   
                    }   
                }   
            }   
        }   
  
        int total = 0;   
        double entropySv = 0;    
        for(int i=0;i&lt;counts.length;i++){   
            total += counts[i];   
        }   
        for(int i=0;i&lt;counts.length;i++){   
            entropySv += DTreeUtil.sigma(counts[i],total);    
        }    
        return DTreeUtil.getPi(total, allTotal)*entropySv;   
    }   
          
    @SuppressWarnings("unchecked")   
    public String[] getArrtibutes(int index) {      
        TreeSet&lt;String> set = new TreeSet&lt;String>(new SequenceComparator());      
        for (int i = 0; i &lt; array.length; i++) {      
            String[] strs = (String[]) array[i];      
            set.add(strs[index]);      
        }      
        String[] result = new String[set.size()];      
        return set.toArray(result);      
    }   
          
    public String getNodeName(int index) {    
    	String[] strs = new String[]{"Outlook","Temperature","Humidity","Wind","Play ball"};
    	for(int i=0;i&lt;strs.length;i++){
    		if(i == index){
    			return strs[i];
    		}
    	}
    	return null;    
    }
    
    public String getLeafNodeName(Object[] array){
    	if(array!=null && array.length>0){
    		String[] strs = (String[])array[0];
    		return strs[index];
    	}
    	return null;		
    }
    
    public int getNodeIndex(String name) {  
    	String[] strs = new String[]{"Outlook","Temperature","Humidity","Wind","Play ball"};
    	for(int i=0;i&lt;strs.length;i++){
    		if(name.equals(strs[i])){
    			return i;
    		}
    	}
        return -1;    
    } 
}      

package graph;      
     
/**    
 * @author B.Chen    
 */     
public class TreeNode {      
     
    /**    
     * 父    
     */     
    TreeNode parent;    
     
    /**    
     * 指向父的哪个属性    
     */     
    String parentArrtibute;      
     
    /**    
     * 节点名    
     */     
    String nodeName;      
     
    /**    
     * 属性数组    
     */     
    String[] arrtibutes;    
    
    /**
     * 节点数组
     */
    TreeNode[] childNodes;

}      

package graph;   
  
public class DTreeUtil {   
  
    /**  
     * 属性值熵的计算 Info(T)=(i=1...k)pi*log（2）pi  
     *   
     * @param x  
     * @param total  
     * @return double  
     */  
    public static double sigma(int x, int total) {
    	if(x == 0){
    		return 0;
    	}
        double x_pi = getPi(x, total);   
        return -(x_pi * logYBase2(x_pi));   
    }   
  
    /**  
     * log2y  
     *   
     * @param y  
     * @return double  
     */  
    public static double logYBase2(double y) {   
        return Math.log(y) / Math.log(2);   
    }   
  
    /**  
     * pi是当前这个属性出现的概率（=出现次数/总数）  
     *   
     * @param x  
     * @param total  
     * @return double  
     */  
    public static double getPi(int x, int total) {   
        return x * Double.parseDouble("1.0") / total;   
    }  

}   

package graph;

import java.util.Comparator;

public class SequenceComparator implements Comparator {

    public int compare(Object o1, Object o2) throws ClassCastException {
        String str1 = (String) o1;
        String str2 = (String) o2;
        return str1.compareTo(str2);
    }

}

</pre>
          <br/>
          <span style="color:red;">
            <a href="http://leon-a.javaeye.com/blog/178585#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 01 Apr 2008 22:18:50 +0800</pubDate>
        <link>http://leon-a.javaeye.com/blog/178585</link>
        <guid>http://leon-a.javaeye.com/blog/178585</guid>
      </item>
      <item>
        <title>ext2.0 的XMLWriter</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://leon-a.javaeye.com/blog/163722" style="color:red;">http://leon-a.javaeye.com/blog/163722</a>&nbsp;
          发表时间: 2008年02月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          做ext相关的一个example项目,把我们的客户端移植成ext2.0的，由于服务器接收的不是JSON数据而是dom，所以我们需要把我们的ajax请求格式对应成服务器支持的格式<br />查了下ext2.0的API，发现只有XMLReader,所以和同事手写XMLWriter<br /><pre name="code" class="java">
/**
 * @author B.Chen
 */
function store2xml(store, xml){
 store.load();
 var array = new Array();
 var old_nodes = xml.documentElement.childNodes;
 var old_firstNodes = old_nodes[0];
 var attributes = old_firstNodes.attributes;
 for(var i=0;i&lt;attributes.length;i++) {
  array[i] = attributes[i].name;
 }
 
 var xmlDoc = createXmlDoc(store);
 var new_nodes = xmlDoc.documentElement.childNodes;
 for(var i=0;i&lt;store.getCount();i++) {
  var record = store.getAt(i);
  for(var j=0;j&lt;array.length;j++) {
   new_nodes[i].setAttribute(array[j],record.get(array[j]));
  }
 }
 return xmlDoc;
}

function createXmlDoc(store){
    var xmlDoc = new ActiveXObject("Microsoft.XMLDOM")
    var xmlString = "";
    var root = "&lt;data>";
    var end_root = "&lt;/data>";
    var child = "&lt;row>"
    var end_child = "&lt;/row>";
    var tab = "\t";
    var nextLine = "\n";
    xmlString += root + nextLine;
    for (var i = 0; i &lt; store.getCount(); i++) {
        xmlString += tab + child + nextLine;
        xmlString += tab + end_child + nextLine;
    }
    xmlString += end_root;
    xmlDoc.loadXML(xmlString)
 return xmlDoc;
}

</pre><br />这个项目从开始接触ext2.0到做好example，用了22天，aptana这个东西不太好用。<br />做好后被客户否决了。。。。。。。汗==|||<br />主要是ext2.0需要import的js类库太大。<br />页面加载的时候容易造成IE假死<br />有lazyrender经验的朋友多指点。。。<br />还有感觉ext2.0虽然华丽，但是做网站的话访问速度。。。估计会很慢，企业局域网应用可以考虑一下
          <br/>
          <span style="color:red;">
            <a href="http://leon-a.javaeye.com/blog/163722#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 20 Feb 2008 21:04:25 +0800</pubDate>
        <link>http://leon-a.javaeye.com/blog/163722</link>
        <guid>http://leon-a.javaeye.com/blog/163722</guid>
      </item>
      <item>
        <title>树与哈夫曼树</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://leon-a.javaeye.com/blog/163721" style="color:red;">http://leon-a.javaeye.com/blog/163721</a>&nbsp;
          发表时间: 2008年02月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
package tree;   
  
public class TreeNode {   
    TreeNode llink;   
    TreeNode rlink;   
    int info;   
}  
package tree;   
  
public class Tree {   
  
    TreeNode root;   
  
    public Tree() {   
    }   
  
    public boolean isEmpty() {   
        return root == null;   
    }   
  
    // 插入   
    public void insertBinaryTree(int info) {   
        TreeNode node = new TreeNode();   
        node.info = info;   
        if (root == null) {   
            root = node;   
        } else {   
            TreeNode currentNode = root;   
            TreeNode parent;   
            while (currentNode != null) {   
                parent = currentNode;   
                if (info > currentNode.info) {   
                    currentNode = currentNode.rlink;   
                    if (currentNode == null) {   
                        parent.rlink = node;   
                    }   
                } else if (info &lt; currentNode.info) {   
                    currentNode = currentNode.llink;   
                    if (currentNode == null) {   
                        parent.llink = node;   
                    }   
                }   
            }   
        }   
    }   
  
    // 删除   
    public void treeDelete(int info) {   
        TreeNode tNode = serach(info);   
        TreeNode deleteNode = new TreeNode();   
        TreeNode dNodeChild = new TreeNode();   
        if (tNode == null) {   
            System.out.println("node is not exists");   
        } else if (tNode.llink == null || tNode.rlink == null) {   
            deleteNode = tNode;   
        } else {   
            deleteNode = treeSuccessor(tNode);   
        }   
        if (deleteNode.llink != null) {   
            dNodeChild = deleteNode.llink;   
        } else {   
            dNodeChild = deleteNode.rlink;   
        }   
        if (getFatherNode(deleteNode) == null) {   
            root = dNodeChild;   
        } else {   
            if (deleteNode == getFatherNode(deleteNode).llink) {   
                getFatherNode(deleteNode).llink = dNodeChild;   
            } else {   
                getFatherNode(deleteNode).rlink = dNodeChild;   
            }   
        }   
        if (deleteNode != tNode) {   
            tNode.info = deleteNode.info;   
        }   
    }   
  
    // 搜索   
    public TreeNode serach(int info) {   
        return treeSerach(root, info);   
    }   
  
    // 搜索   
    public TreeNode treeSerach(TreeNode tNode, int info) {   
        if (tNode == null || tNode.info == info) {   
            return tNode;   
        }   
        if (info &lt; tNode.info) {   
            return treeSerach(tNode.llink, info);   
        } else {   
            return treeSerach(tNode.rlink, info);   
        }   
    }   
  
    // 最大节点   
    public TreeNode treeMaxiMum(TreeNode tNode) {   
        while (tNode.rlink != null) {   
            tNode = tNode.rlink;   
        }   
        return tNode;   
    }   
  
    // 最小节点   
    public TreeNode treeMiniMun(TreeNode tNode) {   
        while (tNode.llink != null) {   
            tNode = tNode.llink;   
        }   
        return tNode;   
    }   
  
    // 找后继   
    public TreeNode treeSuccessor(TreeNode tNode) {   
        if (tNode.rlink != null) {   
            return treeMiniMun(tNode.rlink);   
        }   
        TreeNode currentNode = getFatherNode(tNode);   
        while (currentNode != null && tNode == currentNode.rlink) {   
            tNode = currentNode;   
            currentNode = getFatherNode(tNode);   
        }   
        return currentNode;   
    }   
  
    // 找前驱   
    public TreeNode treePrecursor(TreeNode tNode) {   
        if (tNode.llink != null) {   
            return treeMaxiMum(tNode.llink);   
        }   
        TreeNode currentNode = getFatherNode(tNode);   
        while (currentNode != null && tNode == currentNode.llink) {   
            tNode = currentNode;   
            currentNode = getFatherNode(tNode);   
        }   
        return currentNode;   
    }   
  
    // 找节点的父节点   
    public TreeNode getFatherNode(TreeNode tNode) {   
        TreeNode current = root;   
        TreeNode trailCurrent = null;   
        while (current != null) {   
            if (current.info == tNode.info) {   
                break;   
            }   
            trailCurrent = current;   
            if (tNode.info &lt; current.info) {   
                current = current.llink;   
            } else {   
                current = current.rlink;   
            }   
        }   
        return trailCurrent;   
    }   
  
    // 中序遍历   
    public void inOrder(TreeNode tNode) {   
        if (tNode != null) {   
            inOrder(tNode.llink);   
            System.out.print(tNode.info + " ");   
            inOrder(tNode.rlink);   
        }   
    }   
  
    // 打印树   
    public void printTree() {   
        System.out.println("inOrder");   
        inOrder(root);   
        System.out.println();   
        System.out.println("preOrder");   
        preOrder(root);   
        System.out.println();   
        System.out.println("postOrder");   
        postOrder(root);   
        System.out.println();   
    }   
  
    // 前序遍历   
    public void preOrder(TreeNode tNode) {   
        if (tNode != null) {   
            System.out.print(tNode.info + " ");   
            preOrder(tNode.llink);   
            preOrder(tNode.rlink);   
        }   
    }   
  
    // 后序遍历   
    public void postOrder(TreeNode tNode) {   
        if (tNode != null) {   
            postOrder(tNode.llink);   
            postOrder(tNode.rlink);   
            System.out.print(tNode.info + " ");   
        }   
    }   
  
    public static void main(String[] args) {   
        Tree tree = new Tree();   
        System.out.println("insert tree start");   
        tree.insertBinaryTree(15);   
        tree.insertBinaryTree(5);   
        tree.insertBinaryTree(16);   
        tree.insertBinaryTree(3);   
        tree.insertBinaryTree(12);   
        tree.insertBinaryTree(20);   
        tree.insertBinaryTree(10);   
        tree.insertBinaryTree(13);   
        tree.insertBinaryTree(18);   
        tree.insertBinaryTree(23);   
        tree.insertBinaryTree(6);   
        tree.insertBinaryTree(7);   
        System.out.println("insert tree end");   
        System.out.println("print tree start");   
        tree.treeDelete(15);   
        tree.printTree();   
        System.out.println("print tree end");   
  
    }   
}     

</pre><br />哈夫曼树<br /><pre name="code" class="java">
package tree;   
  
/**  
 * @author B.Chen  
 */  
public class HuffmanTree {   
  
    /**  
     * 根节点  
     */  
    public TreeNode root;   
  
    /**  
     * 数组下表  
     */  
    public int nodeSize;   
  
    /**  
     * 长度  
     */  
    public int length;   
  
    /**  
     * 哈夫曼节点数组  
     */  
    public TreeNode[] nodeList;   
       
    /**  
     * 访问控制  
     */  
    public boolean[] visited;   
  
    /**  
     * @param length  
     */  
    public HuffmanTree(int length) {   
        this.length = length;   
        nodeList = new TreeNode[2 * length-1];   
        visited = new boolean[2*length-1];   
    }   
  
    /**  
     * @param info  
     */  
    public void addNode(int info) {   
        TreeNode tNode = new TreeNode();   
        tNode.info = info;   
        if (nodeSize &lt; length) {   
            nodeList[nodeSize++] = tNode;   
        } else {   
            System.out.println("out of size");   
        }   
    }   
       
    /**  
     * 构造哈夫曼树  
     */  
    public void createHuffmanTree() {   
        int j = length;   
        while (nodeList[2*length -2] == null) {   
            TreeNode lNode = getMiniMumNode();   
            TreeNode rNode = getMiniMumNode();   
            TreeNode tNode = new TreeNode();   
            System.out.println(lNode.info + " " + rNode.info);   
            tNode.llink = lNode;   
            tNode.rlink = rNode;   
            tNode.info = lNode.info + rNode.info;   
            nodeList[j++] = tNode;   
        }   
        root = nodeList[2 * length - 2];   
    }   
       
    /**  
     * @return TreeNode  
     */  
    public TreeNode getMiniMumNode() {   
        TreeNode tNode = null;   
        int size = 0;   
        for(int i=0;i&lt;2*length-1;i++) {   
            if(!visited[i] && nodeList[i] != null) {   
                tNode = nodeList[i];   
                size = i;   
                for(int j=0;j&lt;2*length-1;j++) {   
                    if(!visited[j] && nodeList[j] != null) {   
                        if(tNode.info > nodeList[j].info) {   
                            tNode = nodeList[j];   
                            size = j;   
                        }   
                    }   
                }   
            }   
        }   
        visited[size] = true;   
        return tNode;   
    }   
       
    /**  
     * 中序遍历  
     *   
     * @param tNode  
     */  
    public void inOrder(TreeNode tNode) {   
        if (tNode != null) {   
            inOrder(tNode.llink);   
            System.out.print(tNode.info + " ");   
            inOrder(tNode.rlink);   
        }   
    }   
       
    /**  
     * 打印  
     */  
    public void printHuffmanTree() {   
        System.out.println("inOrder");   
        inOrder(root);   
    }   
       
    /**  
     * @param args  
     */  
    public static void main(String[] args) {   
        HuffmanTree hTree = new HuffmanTree(6);   
        hTree.addNode(4);   
        hTree.addNode(4);   
        hTree.addNode(4);   
        hTree.addNode(4);   
        hTree.addNode(5);   
        hTree.addNode(6);   
        hTree.createHuffmanTree();   
        hTree.printHuffmanTree();   
    }   
}  

</pre>
          <br/>
          <span style="color:red;">
            <a href="http://leon-a.javaeye.com/blog/163721#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 20 Feb 2008 20:50:51 +0800</pubDate>
        <link>http://leon-a.javaeye.com/blog/163721</link>
        <guid>http://leon-a.javaeye.com/blog/163721</guid>
      </item>
      <item>
        <title>LCS与图算法</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://leon-a.javaeye.com/blog/163719" style="color:red;">http://leon-a.javaeye.com/blog/163719</a>&nbsp;
          发表时间: 2008年02月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          求两个字符串最长公共子串的问题。大体解法是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况，若是匹配则为1，否则为0。然后求出对角线最长的1序列，其对应的位置就是最长匹配子串的位置. <br /><pre name="code" class="java">
package graph;   
  
/**  
 * @author B.Chen  
 */  
public class LCS {   
  
    /**  
     * @param a  
     * @param b  
     * @return lcs string  
     */  
    public String lcs(String a, String b) {   
        if (a.length() == 0 || b.length() == 0) {   
            return "";   
        }   
        int[][] matrix = new int[a.length() + 1][b.length() + 1];   
        for (int i = 0; i &lt; a.length() + 1; i++) {   
            matrix[i][0] = 0;   
        }   
        for (int i = 0; i &lt; b.length() + 1; i++) {   
            matrix[0][i] = 0;   
        }   
        String[] arrayA = a.split("");   
        String[] arrayB = b.split("");   
        int maxloop = 0;   
        int position = 0;   
        for (int i = 1; i &lt; a.length() + 1; i++) {   
            for (int j = 1; j &lt; b.length() + 1; j++) {   
                if (arrayA[i - 1].equals(arrayB[j - 1])) {   
                    matrix[i][j] = matrix[i - 1][j - 1] + 1;   
                    if (matrix[i][j] > maxloop) {   
                        maxloop = matrix[i][j];   
                        position = i;   
                    }   
                } else {   
                    matrix[i][j] = 0;   
                }   
            }   
        }   
        StringBuffer result = new StringBuffer();   
        if (maxloop == 0) {   
            return "";   
        }   
        for (int i = position - maxloop; i &lt; position; i++) {   
            result.append(arrayA[i]);   
        }   
        return result.toString();   
    }   
  
    /**  
     * @param a  
     * @param b  
     * @return int lcs length  
     */  
    public int maxLength(String a, String b) {   
        String length = lcs(a, b);   
        return length.length();   
    }   
  
}  

</pre><br /><br /><pre name="code" class="java">
package graph;   
  
public class GraphNode {   
    public GraphNode link;   
    public int info;   
}  
package graph;   
  
public class GraphList {   
  
    public GraphNode first;   
    public GraphNode last;   
    public boolean visitable;   
    public int getAjd(int[] ajd) {   
        GraphNode current = first;   
        int length = 0;   
        while(current != null) {   
            ajd[length++] = current.info;   
            current = current.link;   
        }   
        return length;   
    }   
    public void addNode(int v) {   
        GraphNode node = new GraphNode();   
        node.info = v;   
        if(first == null) {   
            first = node;   
            last = node;   
        } else {   
            last.link = node;   
            last = node;   
        }   
    }   
}  
package graph;   
  
/**  
 * @author B.Chen  
 *  
 */  
public class Graph {   
  
    /**  
     * 节点数  
     */  
    private int length;   
  
    /**  
     * 链表  
     */  
    private GraphList[] list;   
  
    /**  
     * 权集  
     */  
    private int[][] weight;   
       
    /**  
     * 轻边集  
     */  
    private int[][] lightSide;   
       
    /**  
     * 等价类  
     */  
    private int[] replaceValue;   
  
    /**  
     * @param length  
     */  
    public Graph(int length) {   
        this.length = length;   
        list = new GraphList[length];   
        weight = new int[length][length];   
        lightSide = new int[length][length];   
        replaceValue = new int[length];   
        for(int i=0;i&lt;length;i++) {   
            replaceValue[i] = i;   
            for(int j=0;j&lt;length;j++) {   
                weight[i][j] = 9999;   
            }   
        }   
    }   
  
    /**  
     * @param v  
     */  
    public void dfs(int v) {   
        int[] ajd = new int[length];   
        int ajdlength = list[v].getAjd(ajd);   
        list[v].visitable = true;   
        System.out.print(v + " ");   
        for (int i = 0; i &lt; ajdlength; i++) {   
            int w = ajd[i];   
            if (!list[w].visitable) {   
                dfs(w);   
            }   
        }   
    }   
  
    /**  
     * 深度优先遍历     
     */  
    public void dfsTravel() {   
        for (int i = 0; i &lt; length; i++) {   
            list[i].visitable = false;   
        }   
        for (int i = 0; i &lt; length; i++) {   
            if (!list[i].visitable) {   
                dfs(i);   
            }   
        }   
    }   
  
    /**  
     * 广度优先遍历   
     */  
    public void bfsTravel() {   
        for (int i = 0; i &lt; length; i++) {   
            list[i].visitable = false;   
        }   
        bfs();   
    }   
  
    /**  
     * bfs  
     */  
    private void bfs() {   
        Queue queue = new Queue();   
        for (int index = 0; index &lt; length; index++) {   
            if (!list[index].visitable) {   
                queue.addQueue(index);   
                list[index].visitable = true;   
                System.out.print(index + " ");   
                while (!queue.isEmpty()) {   
                    int temp = queue.front();   
                    queue.deleteQueue();   
                    int[] adj = new int[length];   
                    int ajdlength = list[temp].getAjd(adj);   
                    for (int i = 0; i &lt; ajdlength; i++) {   
                        int w = adj[i];   
                        if (!list[w].visitable) {   
                            System.out.print(w + " ");   
                            queue.addQueue(w);   
                            list[w].visitable = true;   
                        }   
                    }   
                }   
            }   
  
        }   
    }   
  
    /**  
     * 长度     
     */  
    public void length() {   
        System.out.println(length);   
    }   
  
    /**  
     * @return boolean  
     */  
    public boolean isEmpty() {   
        return length == 0;   
    }   
  
    /**  
     * @param info  
     */  
    public void addGraph(int info) {   
        for (int i = 0; i &lt; length; i++) {   
            if (list[i] == null) {   
                GraphList g = new GraphList();   
                g.addNode(info);   
                list[i] = g;   
                break;   
            }   
        }   
    }   
  
    /**  
     * 添加有向图的一条边  
     * @param vfrom  
     * @param vto  
     * @param value 权  
     */  
    public void addSide(int vfrom, int vto, int value) {   
        list[vfrom].addNode(vto);   
        weight[vfrom][vto] = value;   
    }   
  
    /**  
     * 添加无向图的一条边  
     * @param vfrom  
     * @param vto  
     * @param value  
     */  
    public void addDoubleSide(int vfrom, int vto, int value) {   
        list[vfrom].addNode(vto);   
        list[vto].addNode(vfrom);   
        weight[vfrom][vto] = value;   
        weight[vto][vfrom] = value;   
    }   
  
    /**  
     * 打印图     
     */  
    public void print() {   
        for (int i = 0; i &lt; length; i++) {   
            GraphNode current = list[i].first;   
            while (current != null) {   
                System.out.print(current.info + " ");   
                current = current.link;   
            }   
            System.out.println();   
        }   
    }   
  
    /**  
     * Dijkstra  
     *   
     * @param v  
     * @return int[]  
     */  
    public int[] shortPath(int v) {   
        int[] shortPath = new int[length];   
        boolean[] weightFound = new boolean[length];   
        for (int i = 0; i &lt; length; i++) {   
            // 趋近无穷   
            shortPath[i] = 9999;   
            weightFound[i] = false;   
        }   
        shortPath[v] = 0;   
        weightFound[v] = true;   
        Queue queue = new Queue();   
        queue.addQueue(v);   
        while (!queue.isEmpty()) {   
            int temp = queue.front();   
            queue.deleteQueue();   
            int[] ajd = new int[length];   
            int ajdlength = list[temp].getAjd(ajd);   
            for (int i = 0; i &lt; ajdlength; i++) {   
                int w = ajd[i];   
                if (!weightFound[w]) {   
                    if (shortPath[w] > shortPath[temp] + weight[temp][w]) {   
                        shortPath[w] = shortPath[temp] + weight[temp][w];   
                    }   
                }   
            }   
            int minWeightNode = 0;   
            for (int i = 0; i &lt; length; i++) {   
                if (!weightFound[i]) {   
                    minWeightNode = i;   
                    for (int j = 0; j &lt; length; j++) {   
                        if (!weightFound[j]) {   
                            if (shortPath[j] &lt; shortPath[minWeightNode]) {   
                                minWeightNode = j;   
                            }   
                        }   
                    }   
                    break;   
                }   
            }   
            if (!weightFound[minWeightNode]) {   
                weightFound[minWeightNode] = true;   
                queue.addQueue(minWeightNode);   
            }   
        }   
        return shortPath;   
    }   
       
    /**  
     * 普里姆最小生成树  
     *   
     * @param v  
     */  
    public void primMST(int v) {   
        boolean[] visited = new boolean[length];   
        for (int i = 0; i &lt; length; i++) {   
            visited[i] = false;   
            for (int j = 0; j &lt; length; j++) {   
                lightSide[i][j] = 9999;   
            }   
        }   
        visited[v] = true;   
        Queue queue = new Queue();   
        queue.addQueue(v);   
        while (!queue.isEmpty()) {   
            int temp = queue.front();   
            queue.deleteQueue();   
            int[] ajd = new int[length];   
            int ajdlength = list[temp].getAjd(ajd);   
            for (int i = 0; i &lt; ajdlength; i++) {   
                int w = ajd[i];   
                lightSide[temp][w] = weight[temp][w];   
            }   
            // 找到最小边   
            int minSide = 0;   
            int vfrom =0;   
            int vto = 0;   
            for (int i = 0; i &lt; length; i++) {   
                for (int j = 0; j &lt; length; j++) {   
                    if (visited[i] && visited[j]) {   
                        continue;   
                    }   
                    minSide = lightSide[i][j];   
                    vfrom = i;   
                    vto = j;   
                    for (int k = 0; k &lt; length; k++) {   
                        for (int l = 0; l &lt; length; l++) {   
                            if (visited[k] && visited[l]) {   
                                continue;   
                            }   
                            if (lightSide[k][l] &lt; minSide) {   
                                minSide = lightSide[k][l];   
                                vfrom = k;   
                                vto = l;   
                            }   
                        }   
                    }   
                    break;   
                }   
            }   
            //将最小边的节点vto设为true，并输出vto   
            if (!visited[vto]) {   
                visited[vto] = true;   
                System.out.print(vfrom+"==>" + vto+", ");   
                queue.addQueue(vto);   
            }   
        }   
    }   
       
    /**  
     * 克鲁斯卡尔最小生成树  
     */  
    public void kruskalMST() {   
        int m = 0;   
        while (m &lt; length - 1) {   
            // 找到最小边   
            int minSide = 0;   
            int vfrom = 0;   
            int vto = 0;   
            for (int i = 0; i &lt; length; i++) {   
                for (int j = 0; j &lt; length; j++) {   
                    if (replaceValue[i] == replaceValue[j]) {   
                        continue;   
                    }   
                    minSide = weight[i][j];   
                    vfrom = i;   
                    vto = j;   
                    for (int k = 0; k &lt; length; k++) {   
                        for (int l = 0; l &lt; length; l++) {   
                            if (replaceValue[k] == replaceValue[l]) {   
                                continue;   
                            }   
                            if (weight[k][l] &lt; minSide) {   
                                minSide = weight[k][l];   
                                vfrom = k;   
                                vto = l;   
                            }   
                        }   
                    }   
                    break;   
                }   
            }   
            if (replaceValue[vfrom] != replaceValue[vto]) {   
                System.out.print(vfrom + "==>" + vto + ", ");   
                for (int i = 0; i &lt; length; i++) {   
                    if (replaceValue[i] == replaceValue[vfrom]) {   
                        replaceValue[i] = replaceValue[vto];   
                    }   
                }   
                m++;   
            }   
        }   
    }   
  
    /**    
     * @param args    
     */  
    public static void main(String[] args) {   
        Graph graph = new Graph(6);   
        System.out.println("create graph start");   
        for (int i = 0; i &lt; 6; i++) {   
            graph.addGraph(i);   
        }   
        graph.addDoubleSide(0, 1, 1);   
        graph.addDoubleSide(0, 2, 8);   
        graph.addDoubleSide(0, 3, 7);   
        graph.addDoubleSide(1, 2, 5);   
        graph.addDoubleSide(1, 4, 5);   
        graph.addDoubleSide(1, 5, 4);   
        graph.addDoubleSide(1, 3, 10);   
        graph.addDoubleSide(2, 4, 3);   
        graph.addDoubleSide(4, 5, 6);   
        graph.addDoubleSide(5, 3, 2);   
        graph.print();   
        System.out.println("create graph end");   
        graph.kruskalMST();   
    }   
}  

</pre><br /><pre name="code" class="java">
/**  
 * 佛洛伊德最短路径  
 *   
 * @param v  
 * @return int[]  
 */  
public int[] floydShortPath(int v) {   
    // 初始化矩阵   
    int[][] spath = new int[length][length];   
    for (int i = 0; i &lt; length; i++) {   
        for (int j = 0; j &lt; length; j++) {   
            if (i == j) {   
                spath[i][j] = 0;   
            } else {   
                spath[i][j] = weight[i][j];   
            }   
        }   
    }   
    for (int i = 0; i &lt; length; i++) {   
        for (int j = 0; j &lt; length; j++) {   
            for (int k = 0; k &lt; length; k++) {   
                if (spath[i][j] + spath[k][i] &lt; spath[j][k]) {   
                    spath[j][k] = spath[i][j] + spath[k][i];   
                }   
            }   
        }   
    }   
    int[] resultArray = new int[length];   
    for (int i = 0; i &lt; length; i++) {   
        resultArray[i] = spath[v][i];   
    }   
    return resultArray;   
  
}  

</pre>
          <br/>
          <span style="color:red;">
            <a href="http://leon-a.javaeye.com/blog/163719#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 20 Feb 2008 20:46:19 +0800</pubDate>
        <link>http://leon-a.javaeye.com/blog/163719</link>
        <guid>http://leon-a.javaeye.com/blog/163719</guid>
      </item>
      <item>
        <title>最近要找新工作，把这一年的东西整理一下，首先是数据结构相关的</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://leon-a.javaeye.com/blog/163718" style="color:red;">http://leon-a.javaeye.com/blog/163718</a>&nbsp;
          发表时间: 2008年02月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在8×8的棋盘上分布着n个骑士，他们想约在某一个格中聚会。骑士每天可以像国际象棋中的马那样移动一次，可以从中间向8个方向移动，请你计算n个骑士的最早聚会地点和要走多少天，要求尽早聚会，且n个人走的总步数最少，先到聚会地点的骑士可以不再移动等待其他的骑士。 <br />从键盘输入n（0&lt;n&lt;=64），然后一次输入n个其实的初始位置xi，yi（0&lt;=xi,y&lt;=7）。屏幕输出以空格分割的三个数，分别为聚会的点（x，y） 以及要走的天数。 <br />　○　○　 <br />○　　　○ <br />　　◎ <br />○　　　○ <br />　○　○　 <br />骑士走法（中间为起始位置，空为走到位置） <br /><pre name="code" class="java">
package convex;   
  
public class Point {   
  
    public int x, y;   
  
    public Point(int x, int y) {   
        if (x > 7 || y > 7) {   
            throw new RuntimeException("out of matrix");   
        }   
        this.x = x;   
        this.y = y;   
    }   
  
    public String toString() {   
        return "x=" + x + ",y=" + y;   
    }   
  
}   
</pre><br /><pre name="code" class="java">
package convex;         
     
import java.io.BufferedReader;      
import java.io.IOException;      
import java.io.InputStreamReader;      
import java.util.StringTokenizer;      
     
import convex.Point;         
        
public class Algo {         
     
    private boolean[][] flg = new boolean[8][8];      
     
    private int[][] shortPath = new int[8][8];      
          
    //最短距离矩阵      
    public int[][] distanceSq(Point p1) {      
        djkst(p1);      
        return shortPath;      
    }      
     
    //BFS       
    private void djkst(Point p1) {      
        Point[] queue = new Point[64];      
        flg[p1.x][p1.y] = true;      
        queue[0] = p1;      
        int j=0;      
        int queueSize = 1;      
        while (j &lt; queue.length) {      
                Point temp = queue[j];      
                Point[] list = getList(temp);      
                for(int i=0;i &lt; list.length;i++) {      
                    if(list[i] != null) {      
                        Point w = list[i];      
                        if (!flg[w.x][w.y]) {      
                            shortPath[w.x][w.y] = shortPath[temp.x][temp.y] + 1;                                  
                            queue[queueSize++] = w;      
                            flg[w.x][w.y] = true;      
                        }      
                    }      
                }      
            j++;      
        }      
    }      
     
    //可行步数集         
    private static Point[] getList(Point point) {      
        Point[] list = new Point[8];      
        int length = 0;      
        if (point.x + 2 &lt;= 7 && point.y + 1 &lt;= 7) {      
            list[length++] = new Point(point.x + 2, point.y + 1);      
        }      
        if (point.x - 2 >= 0 && point.y - 1 >= 0) {      
            list[length++] = new Point(point.x - 2, point.y - 1);      
        }      
        if (point.x + 1 &lt;= 7 && point.y + 2 &lt;= 7) {      
            list[length++] = new Point(point.x + 1, point.y + 2);      
        }      
        if (point.x - 1 >= 0 && point.y - 2 >= 0) {      
            list[length++] = new Point(point.x - 1, point.y - 2);      
        }      
        if (point.x + 2 &lt;= 7 && point.y - 1 >= 0) {      
            list[length++] = new Point(point.x + 2, point.y - 1);      
        }      
        if (point.x - 2 >= 0 && point.y + 1 &lt;= 7) {      
            list[length++] = new Point(point.x - 2, point.y + 1);      
        }      
        if (point.x + 1 &lt;= 7 && point.y - 2 >= 0) {      
            list[length++] = new Point(point.x + 1, point.y - 2);      
        }      
        if (point.x - 1 >= 0 && point.y + 2 &lt;= 7) {      
            list[length++] = new Point(point.x - 1, point.y + 2);      
        }      
        return list;      
    }      
          
    public static int[] method(Point[] points, int i,int j,Object[] pointList) {         
        int maxDay = 0;         
        int distance = 0;      
        for(int k=0;k&lt;pointList.length;k++) {      
            int day = ((int[][])pointList[k])[i][j];      
            distance += day;      
            if(maxDay&lt;day) {      
                maxDay = day;      
            }      
        }      
        return new int[]{maxDay,distance};         
    }      
        
    public static void main(String[] args) throws IOException {      
        //数据输入      
        //数据输入格式：第一个数字是骑士n，第2，3个数字是第一个骑士的坐标，依次类推。      
        //每个数字之间以空格区分      
        BufferedReader stdin =       
            new BufferedReader(      
                new InputStreamReader(System.in));      
     
        String line = stdin.readLine();      
        StringTokenizer st = new StringTokenizer(line);      
        int pointLength = Integer.parseInt(st.nextToken());      
        Point[] points = new Point[pointLength];      
        for(int i=0;i&lt;points.length;i++) {      
            int x = Integer.parseInt(st.nextToken());      
            int y = Integer.parseInt(st.nextToken());      
            points[i] = new Point(x,y);      
        }      
        Object[] pointList = new Object[points.length];      
        for (int j = 0; j &lt; points.length; j++) {         
            pointList[j] = new Algo().distanceSq(points[j]);      
        }      
        int minDay = 999999999;      
        int minDistance = 999999999;        
        for(int i=0;i&lt;7;i++) {      
            for(int j=0;j&lt;7;j++) {      
                int[] result = Algo.method(points, i,j,pointList);         
                //找最短天数，最短天数相同，找最短距离      
                if (minDay > result[0]) {      
                    minDay = result[0];      
                    minDistance = result[1];      
                } else if(minDay == result[0]) {      
                    if(minDistance > result[1]) {      
                        minDistance = result[1];      
                    }      
                }      
            }      
        }      
        for(int i=0;i&lt;7;i++) {      
            for(int j=0;j&lt;7;j++) {      
                int[] result = Algo.method(points, i,j,pointList);    
                if(minDay == result[0] && minDistance == result[1]) {   
                    System.out.println(i+" " + j +" "+ minDay);   
                }   
            }   
        }    
    }      
}     
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://leon-a.javaeye.com/blog/163718#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 20 Feb 2008 20:40:20 +0800</pubDate>
        <link>http://leon-a.javaeye.com/blog/163718</link>
        <guid>http://leon-a.javaeye.com/blog/163718</guid>
      </item>
  </channel>
</rss>