• java数据结构复习02


    1.递归问题

    1.1计算阶乘

    package interview.recursion;
    
    import java.util.Scanner;
    
    public class Fact {
    
        public static void main(String[] args) {
            System.out.println("请输入n的值:");
            Scanner in = new Scanner(System.in);
            int n = in.nextInt();
            int num = fact(n);
            System.out.println(n + "的阶乘为:" + num);
        }
    
        public static int fact(int n) {
            if (n == 1) {
                return 1;
            }
            return n * fact(n - 1);
        }
    }

    1.2计算斐波那契数列

    Fibonacci sequence:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ……

    package interview.recursion;
    
    import java.util.Scanner;
    
    public class Fib {
    
        public static int fib(int n) {
            if (n == 0) {
                return 0;
            } else if (n == 1) {
                return 1;
            } else {
                return fib(n - 1) + fib(n - 2);
            }
    
        }
    
        public static void main(String[] args) {
            System.out.println("请输入n的值:");
            Scanner in = new Scanner(System.in);
            int n = in.nextInt();
            int num = fib(n);
            System.out.println("第" + n + "个值的fib为:" + +num);
        }
    
    }

    1.3计算最大公约数(辗转相除法)

    package interview.recursion;
    
    import java.util.Scanner;
    
    public class Gcd {
        public static int gcd(int max, int min) {
            if (min == 0) {
                return max;
            } else {
                return gcd(min, max % min);
            }
        }
    
        public static void main(String[] args) {
            System.out.println("请输入max的值:");
            Scanner in = new Scanner(System.in);
            int max = in.nextInt();
            System.out.println("请输入min的值:");
            int min = in.nextInt();
            int num = gcd(max, min);
            System.out.println(max + "和" + min + "的最大公约数为:" + num);
        }
    
    }

    1.4汉诺塔问题(递归)

    问题描述
    三个柱子,起初有若干个按大小关系顺序安放的盘子,需要全部移动到另外一个柱子上。移动规则:在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
    移动次数: f(n)=2n -1

    解法思路

    使用递归算法进行处理。

    汉诺塔的算法大概有3个步骤:

    (1)把a上的n-1个盘通过c移动到b。

    (2)把a上的最下面的盘移到c。

    (3)因为n-1个盘全在b上了,所以把b当做a重复以上步骤就好了。

    在网上找到一个3阶的汉诺塔递归过程示意图,参考一下。

    package cn.jxufe.ch06_hanoitowers;
    
    public class HanoiTowers {
        /**
         * 汉诺塔问题:所有的盘子,刚开始都在塔座A上,要求将所有的盘子从塔座A移动到塔座C,每次只能移动一个盘子,且
         * 任何盘子不能放在比自己小的盘子上。
         *
         * @param topN:移动的盘子数
         * @param from:从哪个塔座开始
         * @param inter:中间塔座
         * @param to;目标塔座
         */
        public static void doTower(int topN, char from, char inter, char to) {
            if (topN == 1) {
                System.out.println("盘子1,从" + from + "塔座到" + to + "塔座");
                return;
            } else {
                doTower(topN - 1, from, to, inter);
                System.out.println("盘子" + topN + ",从" + from + "塔座到" + to + "塔座");
                doTower(topN - 1, inter, from, to);
            }
        }
    }
    package cn.jxufe.ch06_hanoitowers;
    
    public class TestHanoiTowers {
        public static void main(String[] args) {
            HanoiTowers.doTower(4,'A','B','C');
        }
    }

    1.5瓶盖问题

    package test;
    /*
     * 描述:每 3 个可乐盖可兑换 1 瓶子可乐,求买 n 瓶可乐最终可获得的可乐瓶子数。
     */
    
    import java.util.Scanner;
    
    public class T03 {
        public static int times = 1;
    
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            System.out.print("输入购买的可乐数:");
    
            times = 1;
    
            int j = input.nextInt();
            int i = func(j);
    
            System.out.println("--------------------------");
            System.out.println("总共可获得 " + i + " 瓶
    
    ");
        }
    
        public static int func(int i) {
            if (i < 3) {
                System.out.println("最终剩下 " + i + " 个瓶盖,不足以兑换");
                return i;
            } else {
                System.out.println("第 " + times++ + " 次兑换," + "本次兑换总共有 " + i + " 个瓶盖,用 " + (i - i % 3) + " 个瓶盖换了 " + i / 3
                        + " 瓶可乐,剩余 " + i % 3 + " 个瓶盖可用于下次兑换");
                return ((i - i % 3) + func(i / 3 + i % 3));
            }
        }
    }

    1.6走楼梯

    题目描述:
    一个台阶总共有n级,如果一次可以跳1级,也可以跳2级。求总共有多少总跳法。

    思路:当n大于2的时候,每次可以选择走2级也可以选择走1级,所有都有两种方案。即f(n-1)+f(n-2)

    package interview.recursion;
    
    import java.util.Scanner;
    
    public class Stairs {
    
        public static int solve(int n) {
            if (n == 1) {
                return 1;
            } else if (n == 2) {
                return 2;
            } else {
                return solve(n - 1) + solve(n - 2);
            }
        }
    
        public static void main(String[] args) {
            System.out.println("请输入n的值:");
            Scanner in = new Scanner(System.in);
            int n = in.nextInt();
            int num = solve(n);
            System.out.println("总共有" + num + "种走法");
        }
    
    }

    2.二叉树 

    2.1插入和查找

    package cn.jxufe.ch07_tree;
    
    /**
     * 二叉树节点
     */
    public class Node {
        //数据项
        public int data;
        public String sdata;
        public Node leftChild;
        public Node rightChild;
    
        public Node(int data,String sdata) {
            this.data = data;
            this.sdata =sdata;
        }
    }
    package cn.jxufe.ch07_tree;
    
    /**
     * 二叉树
     */
    public class Tree {
        //根节点
        public Node root;
    
        /**
         * 插入节点
         */
        public void insert(int value,String sdata) {
            //封装节点
            Node newNode = new Node(value,sdata);
            //引用当前节点
            Node current = root;
            //引用父节点
            Node parent;
            //如果root为null,也就是第一次插入的节点
            if (root == null) {
                root = newNode;
                return;
            } else {
                while (true) {
                    //父节点指向当前节点
                    parent = current;
                    //如果当前节点指向的数据,比插入的要大,则向左走
                    if (value < current.data) {
                        current = current.leftChild;
                        if (current == null) {
                            parent.leftChild = newNode;
                            return;
                        }
                    } else {
                        current = current.rightChild;
                        if (current == null) {
                            parent.rightChild = newNode;
                            return;
                        }
                    }
                }
    
            }
        }
    
        /**
         * 查找节点
         */
        public Node find(int value) {
            //引用当前节点,从根节点开始
            Node current = root;
            //只要查找的值,不等于当前节点的值
            while (current.data != value) {
                //比较查找值,与当前节点值的大小
                if (current.data > value) {
                    current = current.leftChild;
    
                } else {
                    current = current.rightChild;
                }
                //如果查找不到
                if (current == null) {
                    return null;
                }
    
            }
            return current;
    
        }
    
        /**
         * 删除节点
         */
        public void delete(int value) {
    
        }
    }
    package cn.jxufe.ch07_tree;
    
    public class TestTree {
        public static void main(String[] args) {
            Tree tree = new Tree();
            tree.insert(10, "zhangsan");
            tree.insert(20, "lisi");
            tree.insert(3, "wangwu");
            tree.insert(14, "zhaoliu");
            tree.insert(76, "zhouqi");
            System.out.println(tree.root.data);
            System.out.println(tree.root.leftChild.data);
            System.out.println(tree.root.rightChild.data);
            System.out.println(tree.root.rightChild.leftChild.data);
            System.out.println(tree.root.rightChild.rightChild.data);
            Node node = tree.find(20);
            System.out.println(node.data + "," + node.sdata);
            System.out.println(node.rightChild.data + "," + node.rightChild.sdata);
        }
    }

    2.2遍历二叉树

     

    package cn.jxufe.ch07_tree;
    
    /**
     * 二叉树节点
     */
    public class Node {
        //数据项
        public int data;
        public String sdata;
        public Node leftChild;
        public Node rightChild;
    
        public Node(int data,String sdata) {
            this.data = data;
            this.sdata =sdata;
        }
    }
    package cn.jxufe.ch07_tree;
    
    /**
     * 二叉树
     */
    public class Tree {
        //根节点
        public Node root;
    
        /**
         * 插入节点
         */
        public void insert(int value, String sdata) {
            //封装节点
            Node newNode = new Node(value, sdata);
            //引用当前节点
            Node current = root;
            //引用父节点
            Node parent;
            //如果root为null,也就是第一次插入的节点
            if (root == null) {
                root = newNode;
                return;
            } else {
                while (true) {
                    //父节点指向当前节点
                    parent = current;
                    //如果当前节点指向的数据,比插入的要大,则向左走
                    if (value < current.data) {
                        current = current.leftChild;
                        if (current == null) {
                            parent.leftChild = newNode;
                            return;
                        }
                    } else {
                        current = current.rightChild;
                        if (current == null) {
                            parent.rightChild = newNode;
                            return;
                        }
                    }
                }
    
            }
        }
    
        /**
         * 查找节点
         */
        public Node find(int value) {
            //引用当前节点,从根节点开始
            Node current = root;
            //只要查找的值,不等于当前节点的值
            while (current.data != value) {
                //比较查找值,与当前节点值的大小
                if (current.data > value) {
                    current = current.leftChild;
    
                } else {
                    current = current.rightChild;
                }
                //如果查找不到
                if (current == null) {
                    return null;
                }
    
            }
            return current;
    
        }
    
        /**
         * 删除节点
         */
        public void delete(int value) {
    
        }
    
        /**
         * 前序遍历
         */
        public void frontOrder(Node localNode) {
            if (localNode != null) {
                //访问根节点
                System.out.print(localNode.data + ":" + localNode.sdata + "  ");
                //前序遍历左子树
                frontOrder(localNode.leftChild);
                //前序遍历右子树
                frontOrder(localNode.rightChild);
            }
        }
    
        /**
         * 中序遍历
         */
        public void inOrder(Node localNode) {
            if (localNode != null) {
                //中序遍历左子树
                inOrder(localNode.leftChild);
                //访问根节点
                System.out.print(localNode.data + "," + localNode.sdata + "  ");
                //中序遍历右子树
                inOrder(localNode.rightChild);
            }
        }
    
        /**
         * 后序遍历
         */
        public void afterOrder(Node localNode) {
            if (localNode != null) {
                //后序遍历左子树
                afterOrder(localNode.leftChild);
                //后序遍历右子树
                afterOrder(localNode.rightChild);
                //访问根节点
                System.out.print(localNode.data + "," + localNode.sdata + "  ");
            }
        }
    }
    package cn.jxufe.ch07_tree;
    
    public class TestTree {
        public static void main(String[] args) {
            Tree tree = new Tree();
            tree.insert(10, "zhangsan");
            tree.insert(20, "lisi");
            tree.insert(3, "wangwu");
            tree.insert(14, "zhaoliu");
            tree.insert(76, "zhouqi");
            tree.insert(13, "zhuba");
    
            System.out.println("前序遍历:");
            tree.frontOrder(tree.root);
            System.out.println();
            System.out.println("中序遍历:");
            tree.inOrder(tree.root);
            System.out.println();
            System.out.println("后序遍历:");
            tree.afterOrder(tree.root);
    
    
        }
    }

    2.3删除二叉树节点

    package interview;
    
    public class Tree {
        private Node root;
    
        public void insertNode(int data, String sdata) {
            Node newNode = new Node(data, sdata);
            // 引用当前节点
            Node current = root;
            Node parent;
            // 如果root为null,也就是第一次插入
            if (root == null) {
                root = newNode;
            } else {
                while (true) {
                    parent = current;
                    // 如果当前节点指向的数据,比插入的节点数据要大,则向左走
                    if (data < current.data) {
                        current = current.leftChildNode;
                        if (current == null) {
                            parent.leftChildNode = newNode;
                            return;
                        }
                    } else {
                        current = current.rightChildNode;
                        if (current == null) {
                            parent.rightChildNode = newNode;
                            return;
                        }
                    }
                }
            }
    
        }
    
        public Node findNode(int value) {
            Node current = root;
            while (current.data != value) {
                if (current.data > value) {
                    current = current.leftChildNode;
                } else {
                    current = current.rightChildNode;
                }
                if (current == null) {
                    return null;
                }
            }
    
            return current;
        }
    
        public void fontOrder(Node root) {
            if (root != null) {
                System.out.println(root.data);
                fontOrder(root.leftChildNode);
                fontOrder(root.rightChildNode);
            }
        }
    
        public Node getSuccessor(Node delNode) {
            Node successor = delNode;
            Node successorParent = delNode;
            Node current = delNode.rightChildNode;
            while (current != null) {
                successorParent = successor;
                successor = current;
                current = current.leftChildNode;
            }
            if(successor != delNode.rightChildNode) {
                successorParent.leftChildNode = successor.rightChildNode;
                successor.rightChildNode = delNode.rightChildNode;
            }
            return successor;
        }
    
        public boolean deleteNode(int value) {
            // 引用当前节点为根节点
            Node current = root;
            // 引用当前节点的父节点
            Node parent = root;
            // 是否为左子树
            boolean isLeftchild = true;
    
            // 查找
            while (current.data != value) {
                parent = current;
                // 比较
                if (current.data > value) {
                    current = current.leftChildNode;
                    isLeftchild = true;
                } else {
                    current = current.rightChildNode;
                    isLeftchild = false;
                }
                if (current == null) {
                    return false;
                }
            }
    
            // 删除
            if (current.leftChildNode == null && current.rightChildNode == null) {// 1. 删除的节点为叶子节点
                if (current == root) {
                    root = null;
                } else if (isLeftchild) {// 如果它是父节点的左子节点
                    parent.leftChildNode = null;
                } else {
                    parent.rightChildNode = null;
                }
            } else if (current.rightChildNode == null) { // 2. 该节点有一个子节点,且为左子节点
                if (current == root) {
                    root = current.leftChildNode;
                } else if (isLeftchild) {
                    parent.leftChildNode = current.leftChildNode;
                } else {
                    parent.rightChildNode = current.leftChildNode;
                }
            } else if (current.leftChildNode == null) { // 该节点只有一个节点,且为右子节点
                if (current == root) {
                    root = current.rightChildNode;
                } else if (isLeftchild) {
                    parent.leftChildNode = current.rightChildNode;
                } else {
                    parent.rightChildNode = current.rightChildNode;
                }
            }else {
                Node successor = getSuccessor(current);// 查找中序后继节点
                if(current == root) { // 以下是完成替换功能
                    root = successor;
                }else if(isLeftchild) {
                    parent.leftChildNode = successor;
                }else {
                    parent.rightChildNode = successor;
                }
                successor.leftChildNode = current.leftChildNode;
            }
            return true;
        }
    
        public static void main(String[] args) {
            Tree tree = new Tree();
            tree.insertNode(10, "zhangsan");
            tree.insertNode(20, "lisi");
            tree.insertNode(3, "wangwu");
            tree.insertNode(14, "zhaoliu");
            tree.insertNode(76, "zhouqi");
            tree.insertNode(5, "niaho");
            // System.out.println(tree.root.data);
            // System.out.println(tree.root.leftChildNode.data);
            // System.out.println(tree.root.rightChildNode.data);
            // System.out.println(tree.root.rightChildNode.leftChildNode.data);
            // System.out.println(tree.root.rightChildNode.rightChildNode.data);
            // Node node = tree.findNode(20);
            // System.out.println(node.data + "," + node.sdata);
            // System.out.println(node.rightChildNode.data + "," +
            // node.rightChildNode.sdata);
            tree.fontOrder(tree.root);
            tree.deleteNode(3);
            System.out.println("--------------------");
            tree.fontOrder(tree.root);
            tree.deleteNode(20);
            System.out.println("------------------------");
            tree.fontOrder(tree.root);
        }
    }
    
    class Node {
        // 数据域
        public int data;
        public String sdata;
        // 指针域
        public Node leftChildNode;
        public Node rightChildNode;
    
        public Node(int data, String sdata) {
            // TODO Auto-generated constructor stub
            this.data = data;
            this.sdata = sdata;
        }
    
    }

    2.4根据中序和后序,求前序遍历

    package exam;
    
    import java.util.Arrays;
    
    public class Main {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            // Scanner sc = new Scanner(System.in);
    
            // String in = sc.nextLine();
            String in = "dgbaechf";
            char[] inArray = in.toCharArray();
            // String last = sc.nextLine();
            String last = "gbdehfca";
            char[] lastArray = last.toCharArray();
            // System.out.println(Arrays.toString(preArray));
            // System.out.println(Arrays.toString(inArray));
            Node node = buildTree(inArray, lastArray);
            frontOrder(node);
        }
    
        public static Node buildTree(char[] inorder, char[] postorder) {
            if (inorder == null || postorder == null || inorder.length == 0 || postorder.length == 0) {
                return null;
            }
            // 将后序遍历的最后一个节点取出为根
            Node root = new Node(postorder[postorder.length - 1]);
            int i = 0;// 记录中序遍历根的位置
            for (; i < inorder.length; i++) {
                if (postorder[postorder.length - 1] == inorder[i]) {
                    break;
                }
            }
            // 构造左子树
            char[] leftIn = Arrays.copyOfRange(inorder, 0, i);
            char[] leftPost = Arrays.copyOfRange(postorder, 0, i);
            // 构造右子树
            char[] rightIn = Arrays.copyOfRange(inorder, i + 1, inorder.length);
            char[] rightPost = Arrays.copyOfRange(postorder, i, postorder.length - 1);
            // 左子树
            root.leftChild = buildTree(leftIn, leftPost);
            // 右子树
            root.rightChild = buildTree(rightIn, rightPost);
            return root;
        }
    
        /**
         * 前序遍历
         */
        public static void frontOrder(Node localNode) {
            if (localNode != null) {
                // 访问根节点
                System.out.print(localNode.data + "  ");
                // 前序遍历左子树
                frontOrder(localNode.leftChild);
                // 前序遍历右子树
                frontOrder(localNode.rightChild);
            }
        }
    
    }
    
    /**
     * 二叉树节点
     */
    class Node {
        // 数据项
        public char data;
        public Node leftChild;
        public Node rightChild;
    
        public Node(char data) {
            this.data = data;
        }
    }

    2.5二叉树高度

    package datastruct.t04tree;
    
    /**
     * 二叉树节点
     *
     */
    public class Node {
        public int data;
        public Node leftChild;
        public Node rightChild;
    
        public Node(int data) {
            this.data = data;
        }
    
        public void setLeftChild(Node leftChild) {
            this.leftChild = leftChild;
        }
    
        public void setRightChild(Node rightChild) {
            this.rightChild = rightChild;
        }
    
        public static Node createNode(int data) {
            Node node = new Node(data);
            node.leftChild = node.rightChild = null;
            return node;
        }
    
        public static void setChild(Node node, Node leftChild, Node rightChild) {
            node.setLeftChild(leftChild);
            node.setRightChild(rightChild);
        }
    
    }
    package datastruct.t04tree;
    
    public class BiTree {
    
        public static int getTreeHeight(Node root) {
            if (root == null) {
                return 0;
            } else {
                int leftHeight = getTreeHeight(root.leftChild);
                int rightHeight = getTreeHeight(root.rightChild);
                return Math.max(leftHeight, rightHeight) + 1;
            }
    
        }
    
        public static void main(String[] args) {
            // 快速构建一棵二叉树
            Node root = Node.createNode(1);
            Node node2 = Node.createNode(2);
            Node node3 = Node.createNode(3);
            Node node4 = Node.createNode(4);
            Node node5 = Node.createNode(5);
            Node node6 = Node.createNode(6);
            Node node7 = Node.createNode(7);
            Node node8 = Node.createNode(8);
            Node.setChild(root, node2, node3);
            Node.setChild(node2, node4, node5);
            Node.setChild(node3, null, node7);
            Node.setChild(node4, null, node8);
            Node.setChild(node5, node6, null);
            // 树的高度
            int height = getTreeHeight(root);
            System.out.print("树的高度为:");
            System.out.println(height);
    
        }
    
    }

    2.6表达式树的输出与求值

    表达式树的特征:叶节点是运算数,非叶节点一定是运算符

    输入格式:
    第一行给出节点的个数N,每个节点的编号为0 ~ N-1
    接下来N行每行分别给出:
    该节点的编号、该节点的操作数/操作符、该节点的左孩子编号、右孩子编号(-1表示NULL)
    输出格式:
    第一行输出该表达式树的中缀表达式,该用括号的地方需要用括号括起来。
    第二行输出该表达式树的前缀表达式。
    第二行输出该表达式树的后缀表达式。
    第四行输出该表达式树的计算结果,保留两位小数。
    样例输入:

    11
    0 - 1 2
    1 + 3 4
    2 / 5 6
    3 4 -1 -1
    4 * 7 8
    5 6 -1 -1
    6 3 -1 -1
    7 1 -1 -1
    8 - 9 10
    9 5 -1 -1
    10 2 -1 -1

    样例输出:

    (4+(1*(5-2)))-(6/3)
    - + 4 * 1 - 5 2 / 6 3
    4 1 5 2 - * + 6 3 / -
    5.00
    package datastruct.t04tree.exptree;
    
    public class Node {
        char data;
        Node leftChild;
        Node rightChild;
    }
    package datastruct.t04tree.exptree;
    
    import java.util.Scanner;
    
    public class ExpTree {
    
        // 中缀表达式
        public static void inOrder(Node root, int layer) {
            if (root == null)
                return;
            if (root.leftChild == null && root.rightChild == null) {
                // 叶结点是操作数,直接输出,不加括号
                System.out.print(root.data + " ");
            } else {
                // 非叶节点是操作符,需加括号(第0层根节点除外)
                if (layer > 0) {
                    System.out.print("(");
                }
    
                inOrder(root.leftChild, layer + 1);
                System.out.print(root.data + " ");
                inOrder(root.rightChild, layer + 1);
                if (layer > 0) {
                    System.out.print(")");
                }
            }
        }
    
        // 前缀表达式
        public static void preOrder(Node root) {
            if (root == null)
                return;
            System.out.print(root.data + " ");
            preOrder(root.leftChild);
            preOrder(root.rightChild);
    
        }
    
        // 后缀表达式
        public static void postOrder(Node root) {
            if (root == null)
                return;
            postOrder(root.leftChild);
            postOrder(root.rightChild);
            System.out.print(root.data + " ");
        }
    
        public static double getExpTree(Node root) {
            if (root == null) {
                return 0;
            }
            if (root.leftChild == null && root.rightChild == null) {
                // 叶节点,节点存放的是 操作数
                return root.data - '0'; // 将字符转换成数字
            }
            // 非叶结点,节点存放的是 操作符
            double a = getExpTree(root.leftChild);
            double b = getExpTree(root.rightChild);
            return cal(a, b, root.data);
        }
    
        public static double cal(double a, double b, char op) {
            switch (op) {
            case '+':
                return a + b;
            case '-':
                return a - b;
            case '*':
                return a * b;
            case '/':
                return a / b;
            default:
                return 0;
            }
        }
    
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            System.out.println("请输入节点的个数");
            int N = input.nextInt();
    
            Node[] nodes = new Node[N];
            for (int i = 0; i < N; i++) {
                nodes[i] = new Node();
            }
            System.out.println("请输入index,data,l,r");
    
            for (int i = 0; i < N; i++) {
                int index = input.nextInt();
                char data = input.next().charAt(0);
                int l = input.nextInt();
                int r = input.nextInt();
                nodes[index].data = data;
                nodes[index].leftChild = (l != -1 ? nodes[l] : null);
                nodes[index].rightChild = (r != -1 ? nodes[r] : null);
            }
            Node root = nodes[0];
            inOrder(root, 0);
            System.out.println();
            preOrder(root);
            System.out.println();
            postOrder(root);
            System.out.println();
            double value = getExpTree(root);
            System.out.println(value);
        }
    
    }

    2.7求二叉树指定节点所在层数(假设根节点的层数为1)

    1.方法1

    package datastruct.t04tree.layer;
    
    class Node {
        int data;
        Node leftChild;
        Node rightChild;
    
        public Node(int data) {
            this.data = data;
        }
    
        public void setChild(Node leftChild, Node rightChild) {
            this.leftChild = leftChild;
            this.rightChild = rightChild;
        }
    }
    
    public class NodeLayer {
        static int layer = 0;
        static boolean flag = false;// flag标记可用于提前快速结束递归的执行
    
        public static void getNodeLayer(Node root, int value) {
            if (root == null)
                return;
    
            if (flag)
                return;
            layer++;
            if (root.data == value) {
                System.out.println(layer);
                flag = true;
                return;
            }
            getNodeLayer(root.leftChild, value);
            getNodeLayer(root.rightChild, value);
            layer--;
        }
    
        public static void main(String[] args) {
            Node root = new Node(1);
            Node node2 = new Node(2);
            Node node3 = new Node(3);
            Node node4 = new Node(4);
            Node node5 = new Node(5);
            Node node6 = new Node(6);
            Node node7 = new Node(7);
            Node node8 = new Node(8);
            root.setChild(node2, node3);
            node2.setChild(node4, node5);
            node3.setChild(null, node6);
            node5.setChild(node7, null);
            node7.setChild(null, node8);
            int value = 7;
            getNodeLayer(root, value);
        }
    
    }

    2.方法2

    package datastruct.t04tree.layer;
    
    class Node {
        int data;
        Node leftChild;
        Node rightChild;
    
        public Node(int data) {
            this.data = data;
        }
    
        public void setChild(Node leftChild, Node rightChild) {
            this.leftChild = leftChild;
            this.rightChild = rightChild;
        }
    }
    
    public class NodeLayer {
       
        static boolean flag = false;
    
        public static void getNodeLayer(Node root, int value, int layer) {
            if (root == null)
                return;
            if (flag)
                return;
            if (root.data == value) {
                System.out.println(layer);
                flag = true;
                return;
            }
            getNodeLayer(root.leftChild, value, layer + 1);
            getNodeLayer(root.rightChild, value, layer + 1);
    
        }
    
        public static void main(String[] args) {
            Node root = new Node(1);
            Node node2 = new Node(2);
            Node node3 = new Node(3);
            Node node4 = new Node(4);
            Node node5 = new Node(5);
            Node node6 = new Node(6);
            Node node7 = new Node(7);
            Node node8 = new Node(8);
            root.setChild(node2, node3);
            node2.setChild(node4, node5);
            node3.setChild(null, node6);
            node5.setChild(node7, null);
            node7.setChild(null, node8);
            int value = 7;
            getNodeLayer(root, value, 1);
        }
    
    }

    2.8求某节点到根节点的路径

    对于如下二叉树,节点 7 位于第 4 层,其到跟节点的路径为 1 2 5 7

    package datastruct.t04tree.path;
    
    import java.util.Stack;
    
    class Node {
        int data;
        Node leftChild;
        Node rightChild;
    
        public Node(int data) {
            this.data = data;
        }
    
        public void setChild(Node leftChild, Node rightChild) {
            this.leftChild = leftChild;
            this.rightChild = rightChild;
        }
    }
    
    public class TreePath {
        static Stack<Integer> path = new Stack<>();
        static boolean flag = false;
    
        public static void getNodePath(Node root, int value) {
            if (root == null)
                return;
            if (flag)
                return;
            path.add(root.data);
            if (root.data == value) {
                for (Integer integer : path) {
                    System.out.print(integer + " ");
                }
                flag = true;
                return;
            }
            getNodePath(root.leftChild, value);
            getNodePath(root.rightChild, value);
            path.pop();
        }
    
        public static void main(String[] args) {
            Node root = new Node(1);
            Node node2 = new Node(2);
            Node node3 = new Node(3);
            Node node4 = new Node(4);
            Node node5 = new Node(5);
            Node node6 = new Node(6);
            Node node7 = new Node(7);
            Node node8 = new Node(8);
            root.setChild(node2, node3);
            node2.setChild(node4, node5);
            node3.setChild(null, node6);
            node5.setChild(node7, null);
            node7.setChild(null, node8);
            int value = 7;
            getNodePath(root, value);
        }
    
    }

    2.9全排列问题

    输出数字1~N所能组成的所有全排列

    package datastruct.t04tree.permutation;
    
    import java.util.Stack;
    
    public class Permutation {
        public static int MAXN = 10;
        static boolean[] isUsed = new boolean[MAXN];
        static Stack<Integer> nums = new Stack<>();
        static int N;
    
        /**
         * @param index
         *            表示第几层
         */
        public static void DFS(int index) {
            if (index >= N) {
                for (Integer i : nums)
                    System.out.print(i + " ");
                System.out.println();
                return;
            }
            for (int i = 1; i <= N; i++) {
                if (isUsed[i])
                    continue;
                nums.push(i);
                isUsed[i] = true;
                DFS(index + 1);
                nums.pop();
                isUsed[i] = false;
            }
        }
    
        public static void main(String[] args) {
            N = 3;
            DFS(0);// 从第0层开始搜索
        }
    
    }

    3.红黑树

     

    4.hash表

    4.1直接将关键字作为索引

    package ch15;
    
    public class Info {
        private int key;
        private String name;
    
        public Info(int key, String name) {
            // TODO Auto-generated constructor stub
            this.key = key;
            this.name = name;
        }
    
        public int getKey() {
            return key;
        }
    
        public void setKey(int key) {
            this.key = key;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
        
        
    }
    package ch15;
    
    public class HashTable {
        private Info[] arr;
    
        public HashTable() {
            // TODO Auto-generated constructor stub
            arr = new Info[100];
        }
    
        public HashTable(int maxSize) {
            arr = new Info[maxSize];
        }
    
        public void insert(Info info) {
            arr[info.getKey()] = info;
        }
    
        public Info find(int key) {
            return arr[key];
        }
    }
    package ch15;
    
    public class TestHashTable {
        public static void main(String[] args) {
            HashTable hTable = new HashTable();
            hTable.insert(new Info(10, "张三"));
            hTable.insert(new Info(15, "李四"));
    
            System.out.println(hTable.find(15).getName());
        }
    }

    4.2将单词转化为索引

    package ch15;
    
    public class Info {
        private String key;
        private String name;
    
        public Info(String key, String name) {
            // TODO Auto-generated constructor stub
            this.key = key;
            this.name = name;
        }
    
        public String getKey() {
            return key;
        }
    
        public void setKey(String key) {
            this.key = key;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
        
        
    }
    package ch15;
    
    public class HashTable {
        private Info[] arr;
    
        public HashTable() {
            // TODO Auto-generated constructor stub
            arr = new Info[100];
        }
    
        public HashTable(int maxSize) {
            arr = new Info[maxSize];
        }
    
        public void insert(Info info) {
            arr[hashCode(info.getKey())] = info;
        }
    
        public Info find(String key) {
            return arr[hashCode(key)];
        }
    
        public int hashCode(String key) {
            int hashValue = 0;
            for (int i = key.length() - 1; i >= 0; i--) {
                int letter = key.charAt(i) - 96;
                hashValue += letter;
            }
            return hashValue;
        }
    }
    package ch15;
    
    public class TestHashTable {
        public static void main(String[] args) {
            HashTable hTable = new HashTable();
            hTable.insert(new Info("zhangsan", "张三"));
            hTable.insert(new Info("lisi", "李四"));
    
            System.out.println(hTable.find("zhangsan").getName());
        }
    }

    以上方法也会存在一定的问题,当hashcode相同的时候。

    package ch15;
    
    public class TestHashTable {
        public static void main(String[] args) {
            HashTable hTable = new HashTable();
            hTable.insert(new Info("abc", "张三"));
            hTable.insert(new Info("bca", "李四"));
    
            System.out.println(hTable.find("abc").getName());
            System.out.println(hTable.find("bca").getName());
        }
    }

     我们用幂函数的方式去重写hashcode

    public int hashCode(String key) {
            int hashValue = 0;
            int pow27 = 1;
            for (int i = key.length() - 1; i >= 0; i--) {
                int letter = key.charAt(i) - 96;
                hashValue += letter * pow27;
                pow27 *= 27;
            }
            return hashValue;
        }
    package ch15;
    
    public class TestHashTable {
        public static void main(String[] args) {
            HashTable hTable = new HashTable();
            hTable.insert(new Info("abc", "张三"));
            hTable.insert(new Info("bca", "李四"));
    
            System.out.println(hTable.find("abc").getName());
            System.out.println(hTable.find("bca").getName());
        }
    }

     此时可以解决上面的问题,但是浪费太多内存了,因为字符串如果很长,数组容易越界或者内存溢出,因此需要进行取模运算。

    public int hashCode(String key) {
            BigInteger hashValue = new BigInteger("0");
            BigInteger pow27 = new BigInteger("1");
            for (int i = key.length() - 1; i >= 0; i--) {
                int letter = key.charAt(i) - 96;
                BigInteger letterB = new BigInteger(String.valueOf(letter));
                hashValue = hashValue.add(letterB.multiply(pow27));
                pow27 = pow27.multiply(new BigInteger(String.valueOf(27)));
            }
            return hashValue.mod(new BigInteger(String.valueOf(key.length()))).intValue();
        }
  • 相关阅读:
    转发和重定向的区别
    关于Daydream VR的最直白的介绍
    Duplicate Protocol Definition of DTService Is Ignored
    automatically select architectures
    java
    初识反射
    java网络编程
    Map接口
    Set,List
    正则表达式
  • 原文地址:https://www.cnblogs.com/xinmomoyan/p/11270109.html
Copyright © 2020-2023  润新知