博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

java数据结构复习02

Posted on 2019-07-30 15:02  心默默言  阅读(346)  评论(0编辑  收藏  举报

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 + " 瓶\n\n");
    }

    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();
    }