Java实现查找树(BST,AVL,BTree,Trie)

BST

二叉排序树是一种非常简单的排序树(或者说查找树)
包括两种操作

添加

添加的元素永远是叶子节点

删除

  1. 叶子节点,直接删除
  2. 非叶子节点
    2.1. 只有左子树或者只有右子树,直接用左子树或者右子树代替待删除节点
    2.2. 如果左右子树都存在,则将右子树接到左子树的最右边节点的右子树下,这样就依然保持了有序
import java.util.*;
/* * 二分法查找 */
public class BST {
    public static Node root = null;

    public static void main(String[] args) 
    {
        System.out.println("Hello World!");
        int[] values = createValue();
        //int[] values = {10,8,13,4,14,2,6,1,3,5,7};
        //int[] values = {1};
        //int[] values = {10,8,4,2,6,1,3,5,7};
        System.out.println(Arrays.toString(values));
        createBST(values);
        printBST(root);
        System.out.println();
        System.out.print("Pls. select a operation(s for search, a for add, d for delete, q for quit,p for print):");
        Scanner scan = new Scanner(System.in);
        String str = scan.next();
        char select = str.charAt(0);
        while(true){
            if(select == 'q'){
                break;
            }
            int key = 0;
            switch (select)
            {

                case 'a':
                    System.out.println();
                    System.out.print("(a)Input a integer:");
                    key = scan.nextInt();
                    addNode(key);
                    printBST(root);
                    break;
                case 'd':
                    System.out.println();
                    System.out.print("(d)Input a integer:");
                    key = scan.nextInt();
                    deleteNode(key);
                    printBST(root);
                    break;
                case 'p':
                    printBST(root);
                    break;
                case 's':
                    System.out.println();
                    System.out.print("(s)Input a integer:");
                    key = scan.nextInt();
                    if(search(key)){
                        System.out.println(key + "存在!");
                    }else{
                        System.out.println(key + "不存在!");
                    }
                    break;
            }
            System.out.println();
            System.out.print("Pls. select a operation(s for search, a for add, d for delete, q for quit,p for print):");
            str = scan.next();
            select = str.charAt(0);
        }

    }
    /* * 产生随机的整数数组 */
    public static int[] createValue(){
        int size = new Random().nextInt(20);
        while(size == 0){
            size = new Random().nextInt(20);
        }
        int[] values = new int[size];
        for(int i = 0; i < size ; i ++ ){
            values[i] = new Random().nextInt(20000);
        }
        return values;
    }
    /* * 构造BST * */
    public static void createBST(int[] value){

        for(int i = 0; i < value.length; i ++){
            addNode(value[i]);
        }
    }
    /* * 中序遍历BST */
    public static void printBST(Node p){
        if(p == null){
            return;
        }else{
            printBST(p.left);
            System.out.print(p.key+",");
            printBST(p.right);
        }
        //System.out.println();
    }
    /* * 查找 */
    public static boolean search(int key){
        Node p = root; 
        while(p != null){
            if(p.key == key){
                return true;
            }else if(key < p.key){
                p = p.left;
            }else{
                p = p.right;
            }

        }
        return false;
    }
    /* * 添加节点 */
    public static boolean addNode(int key){
        //BST 是空树
        if(root == null){
            root = new Node(key);
        }else{
            Node p = root;
            while(true){
                int tmp = p.key;
                if(key == tmp ){
                    return false;
                }else if(key < p.key){
                    if(p.left == null){
                        Node q = new Node(key);
                        p.left = q;
                        return true;
                    }else{
                        p = p.left;
                    }
                }else{
                    if(p.right == null){
                        Node q = new Node(key);
                        p.right = q;
                        return true;
                    }else{
                        p = p.right;
                    }
                }
            }
        }
        return true;
    }
    /* * 删除节点 */
    public static boolean deleteNode(int key){
        Node q = null;
        Node p = root;
        //标识当前节点是父节点的左节点(true)
        //还是父节点的右节点(false)
        boolean flag = false;
        while(p != null){
            System.out.println("p.key:"+p.key);
            if(p.key == key){
                //p是叶子节点
                if(p.left == null && p.right == null){
                    if(q == null){
                        root = null;
                    }else{
                        if(flag){
                            q.left = null;
                        }else{
                            q.right = null;
                        }
                    }
                }
                //p的左子树或右子树是空
                else if(p.left == null || p.right == null){
                    if(q == null){
                        root = (p.left == null ? p.right: p.left);
                    }else{
                        if(flag){
                            q.left = (p.left == null ? p.right: p.left);
                        }else{
                            q.right = (p.left == null ? p.right: p.left);
                        }
                    }
                }
                //左右子树都不为空
                else{
                    Node k = p.left;
                    while(k.right != null){
                        k = k.right;
                    }
                    if(q == null){
                        k.right = p.right;
                        root = p.left;
                    }else{
                        k.right = p.right;
                        q.left = p.left;
                    }
                }
                return true;
            }else if(key < p.key){
                q = p;
                p = p.left;
                flag = true;
            }else{
                q = p;
                p = p.right;
                flag = false;
            }
        }
        return false;
    }
}

AVL

这是一种比BST高效的平衡二叉树,
高度为 h 的 AVL 树,节点数 N 最多2^h − 1; 最少N(h)=N(h− 1) +N(h− 2) + 1。
查找、插入和删除在平均和最坏情况下都是O(log n)
主要是几个旋转操作
左旋,右旋,双向旋转(先左后右,先右后左)

import java.util.*;

/* * 自平衡二叉查找树 */
public class AVL {
    private static Node root = null;
    private static int count = 0;

    public static void main(String[] args) 
    {
        System.out.println("Hello World!");
        int[] values = createData();
        System.out.println("原始数组:" + Arrays.toString(values));
        createAVL(values);
        printAVL();
        //System.out.println(height(root.left));
        //System.out.println(height(root.right));
    }
    /* * 创建测试数据 */
    public static int[] createData(){
        int size = new Random().nextInt(20);
        while(size == 0){
            size = new Random().nextInt(20);
        }
        int[] values = new int[size]; 
        for(int i = 0; i < size; i ++){
            values[i] = new Random().nextInt(100);
        }
        return values;
    }
    /* * 构造树 */
    public static void createAVL(int[] values){
        for(int i = 0; i < values.length; i ++){
            addNode(values[i]);
        }
    }
    /* * 添加节点 */
    public static void addNode(int key){
        Node tmp = new Node(key);
        if(root == null){
            root = tmp;
        }else{
            insert(tmp);
            balance(tmp);
        }
    }
    /* * 插入节点 */
    public static void insert(Node tmp){
        Node q = root;
        while(true){
            if(tmp.key == q.key){
                return;
            }else if(tmp.key < q.key){
                if(q.left == null){
                    q.left = tmp;
                    break;
                }
                q = q.left;
            }else{
                if(q.right == null){
                    q.right = tmp;
                    break;
                }
                q = q.right;
            }
        }
    }
    /* * 平衡节点 * 由于插入tmp节点,树失去了平衡 */
    public static void balance(Node tmp){
        //p是离插入节点最近的非平衡节点
        Node p = null;
        //q用来遍历AVL树
        Node q = null;
        q = root;
        //1. 寻找离tmp最近的非平衡点q
        while(q != null){
            int hL = height(q.left);    
            int hR = height(q.right);
            if(((hL - hR) == 2) || ((hL - hR)== -2)){
                //此节点是非平衡点,用p标记
                p = q;
            }
            if(tmp.key < q.key){
                q = q.left;
            }else if(tmp.key > q.key){
                q = q.right;
            }else{
                q = null;
            }
        }
        if(p == null){
            //不存在非平衡点
            return;
        }
        //2. 判断属于哪种情况
        //2.1 在p的左孩子的左子树中插入节点-- 右旋
        //2.2 在p的左孩子的右子树中插入节点-- 先左再右
        //2.3 在p的右孩子的左子树中插入节点-- 先右再左
        //2.4 在p的右孩子的右子树中插入节点-- 左旋
        if(tmp.key < p.key){
            if(tmp.key < p.left.key){
                //右旋
                singleRotate(p,false);
                //System.out.println("平衡之后:");
                //printAVL();
            }else{
                //左-右,先左旋后右旋
                //System.out.println("左-右");
                doubleRotate(p,true);
            }
        }else{
            if(tmp.key > p.right.key){
                //左旋
                singleRotate(p,true);
            }else{
                //右-左
                //System.out.println("右-左");
                doubleRotate(p,false);
            }
        }
    }
    /* * 将以p为根的树单次旋转 */
    public static void singleRotate(Node p,boolean flag){
        //左旋
        if(flag){
            Node r = p.right;
            Node tmp = Node.copy(p);
            tmp.right = r.left;
            p.right = r.right;
            p.key = r.key;
            p.left = tmp;
        }
        //右旋
        else{
            Node left = p.left;
            Node tmp = Node.copy(p);
            tmp.left = left.right;
            p.left = left.left;
            p.key = left.key;
            p.right = tmp;
        }
    }
    /* * 以p为根的双旋 */
    public static void doubleRotate(Node p,boolean flag){
        //先左旋后右旋
        if(flag){
            Node q = p.left;
            singleRotate(q,true);
            singleRotate(p,false);
        }
        //先右旋后左旋
        else{
            Node q = p.right;
            singleRotate(q,false);
            singleRotate(p,true);
        }
    }
    /* * 二叉树的高度 */
    public static int height(Node p){
        if(p == null){
            return 0;
        }
        int hL = height(p.left);
        int hR = height(p.right);
        return (hL > hR ? hL: hR) + 1;
    }
    /* * 按层次输出树,空节点以"N"表示 */
    public static void printAVL(){
        Queue<Node> queue = new LinkedList<Node>();
        System.out.print("[");
        if(root != null){
            queue.offer(root);
            Node p = null;
            while(!queue.isEmpty()){
                p = queue.poll();
                if(p != null){
                    System.out.print(p.key+",");
                    if(p.left != null){
                        queue.offer(p.left);
                    }else{
                        queue.offer(null);
                    }
                    if(p.right != null){
                        queue.offer(p.right);
                    }else{
                        queue.offer(null);
                    }
                }   
                else
                    System.out.print("N,");
            }
        }
        System.out.println("]");
    }
}


class Node
{
    /* * balanceFactor=H(left) - H(right) */
    int key = 0;
    Node left;
    Node right;
    public Node(int key){
        this.key =  key;
    }

    public static Node copy(Node p){
        Node tmp = new Node(p.key);
        tmp.left = p.left;
        tmp.right = p.right;
        return tmp;
    }
}

BTree

平衡多路查找树

import java.util.*;

/* * m阶的B-树,或为空树,或为满足下列特性的m叉树 * 1. 树中每个节点至多有m棵子树(m-1个关键字) * 2. 若根节点不是叶子节点则至少有两棵子树 * 3. 除根之外的所有非终端节点至少有ceil(m/2)棵子树(ceil(m/2)-1个关键字) * 4. 所有的非终端节点中包含下列信息数据 * (n,A0,K1,A1,K2,A2,...,Kn,An) * 其中:Ki(i=1,...,n)为关键字,且Ki<Ki+1(i=1,...,n-1); * Ai(i=0,...,n)为指向子树根节点的指针, * 且指针Ai-1所指子树中所有节点的关键字均小于Ki(i=1,...,n) * An所指子树中所有节点的关键字均大于Kn,n(ceil(m/2)-1 <= n <= m-1)为关键字的个数 * 5. 所有的叶子节点都出现在同一层次上,并且不带信息(可以看做是外部节 * 点或查找失败的节点,实际上这些节点不存在,指向这些节点的指针为空) * * 分裂时,将(关键字-1)一分为二,然后将中间的放到父节点中 * 分裂函数写的时候,要注意父节点指针的更改 */

public class BTree {
    //表示这棵BTree是m阶,每个节点最多M棵子树,M-1个关键字
    private static final int M;
    //每个节点至少MIN_KEY_NUM个子树,MIN_KEY_NUM - 1 个关键字
    private static final int MIN_KEY_NUM;

    private static BTreeNode root;

    static{
        M = 3;
        //注意是2.0,而不是2
        MIN_KEY_NUM = (int)Math.ceil(M/2.0);
    }
    public static void main(String[] args) 
    {
        System.out.println("Hello World!");

        int count = new Random().nextInt(10);
        while(count == 0){
            count = new Random().nextInt(10);
        }
        int[] arr = new int[count];
        for(int i = 0; i < count ; i ++){
            arr[i] = new Random().nextInt(100);
        }
        int[] arr1 = {62,65,92};
        System.out.println(Arrays.toString(arr));
        createBTree(arr);
        printBTree();
        System.out.println("============删除===============");
        while(count > 0){
            int index = new Random().nextInt(count);
            System.out.println("删除:" + arr[index]);
            delete(arr[index]);
            printBTree();
            for(int i = 0; i < count ; i ++){
                if(i > index){
                    arr[i - 1] = arr[i];
                }
            }
            count--;
        }
    }
    public static void createBTree(int[] arr){

        for(int i = 0; i < arr.length ; i ++){
            //System.out.println(i);
            add(arr[i]);
        }
    }
    public static void add(int key){
        //根为空
        if(root == null){
            root = new BTreeNode();
            root.keys[++root.keyNum] = key;
            root.parrent = null;
            return;
        }
        BTreeNode p = root;
        label:
            while(true){

                //插入排序
                int i = 0;
                for(i = p.keyNum; i >= 1 ; i--){
                    //找寻插入点
                    if(key > p.keys[i]){
                        break;
                    }
                    if(key == p.keys[i]){
                        return;
                    }
                }
                if(p.childs[i] == null){
                    //插入点为i+1
                    for(int j = p.keyNum ; j >= (i + 1); j--){
                        p.keys[j + 1] = p.keys[j];
                    }

                    p.keys[i + 1] = key;
                    p.keyNum++;
                    break label;
                }else{
                    p = p.childs[i];
                }
            }
        //将key插入p之后,判断p节点是否符合BTree的条件
        //每个节点的关键字最多M-1个
        if(p.keyNum > M - 1){

            //将p节点分裂
            split(p);
        }
    }
    private static void split(BTreeNode p){
        BTreeNode lt = new BTreeNode();
        BTreeNode gt = new BTreeNode();
        //分裂出来的左节点
        /* * M = 3 * MIN_KEY_NUM = 2 * keys: * ----------------- * |0 |1 |2 |3 | * ----------------- * childs: * ----------------- * |0 |1 |2 |3 | * ----------------- * index = M 的值作为备用 */

        System.arraycopy(p.keys,1,lt.keys,1,MIN_KEY_NUM - 1);
        System.arraycopy(p.childs,0,lt.childs,0,MIN_KEY_NUM);
        lt.keyNum = MIN_KEY_NUM - 1;
        //System.out.println(p.keys[MIN_KEY_NUM] + ":" + Arrays.toString(lt.keys));

        System.arraycopy(p.keys,MIN_KEY_NUM + 1,gt.keys,1,M - MIN_KEY_NUM);
        System.arraycopy(p.childs,MIN_KEY_NUM,gt.childs,0,M - MIN_KEY_NUM + 1);
        gt.keyNum = M - MIN_KEY_NUM;
        //System.out.println(p.keys[MIN_KEY_NUM] + ":" + Arrays.toString(gt.keys));
        /* * 分隔节点之后,需要更改父节点信息 */
        for(int i = 0 ; i <= lt.keyNum ; i ++){
            if(lt.childs[i] != null){
                lt.childs[i].parrent = lt;
            }
        }
        for(int i = 0 ; i <= gt.keyNum ; i ++){
            if(gt.childs[i] != null){
                gt.childs[i].parrent = gt;
            }
        }

        BTreeNode parrent = p.parrent;
        //root节点分裂
        if(parrent == null){
            BTreeNode tmp = new BTreeNode();
            tmp.keys[++tmp.keyNum] = p.keys[MIN_KEY_NUM];
            tmp.parrent = null;
            tmp.childs[tmp.keyNum - 1] = lt;
            tmp.childs[tmp.keyNum] = gt;
            lt.parrent = tmp;
            gt.parrent = tmp;
            root = tmp;
        }else{
            int i = 0;
            //System.out.println("parrent:"+Arrays.toString(parrent.keys));
            //插入排序
            for(i = parrent.keyNum; i >= 1 ; i--){
                //找寻插入点
                if(p.keys[MIN_KEY_NUM] > parrent.keys[i]){
                    break;
                }
            }
            //插入点为i+1
            for(int j = parrent.keyNum ; j >= (i + 1); j--){
                parrent.keys[j + 1] = parrent.keys[j];
                parrent.childs[j + 1] = parrent.childs[j];
            }
            parrent.keys[i + 1] = p.keys[MIN_KEY_NUM];
            //System.out.println("parrent:"+Arrays.toString(parrent.keys));
            parrent.childs[i] = lt;
            parrent.childs[i + 1] = gt;
            lt.parrent = parrent;
            gt.parrent = parrent;
            parrent.keyNum++;
            //System.out.println("parrent:"+parrent.keyNum);
            //是否继续分裂
            if(parrent.keyNum > M - 1){
                //将p节点分裂
                split(parrent);
            }
        }
    } 
    /* * 删除节点i中的key * 1. 节点i不是最底层非终端节点 * 将Ai子树上的最小值替换key * 问题变为2 * 2. 节点i是最底层非终端节点 * 2.1 节点i的关键字个数 >= MIN_KEY_NUM,直接删除 * 2.2 节点i的关键字个数 = MIN_KEY_NUM - 1 * 2.2.1 兄弟节点的关键字个数 >= MIN_KEY_NUM,将右兄弟最小值(左兄弟最大值)上移至父节点相应位置的数据,然后将父节点被替换的数据下移至被删除节点 * 2.2.2 兄弟节点的关键字个数 = MIN_KEY_NUM - 1,合并(借助父节点) * */
    public static void delete(int key){
        //System.out.println("deletekey:" + key);
        //遍历BTree,查找key所在的节点
        BTreeNode p = root;
        int index = 0;
        label:
        while(p != null){
            //System.out.println("p.keyNum:" + p.keyNum);
            //System.out.println("p:" + Arrays.toString(p.keys));
            for(int i = p.keyNum; i >= 1; i --){
                if(key == p.keys[i]){
                    index = i;
                    break label;
                }else if(key > p.keys[i]){
                    p = p.childs[i];
                    continue label;
                }
            }
            p = p.childs[0];
        }
        if(p == null){
            return ;
        }
        //System.out.println("p.keyNum:" + p.keyNum);
        //System.out.println("p:" + Arrays.toString(p.keys));
        //找到p
        if(p.childs[0] == null){
            delete(p,key);
        }else{
            //对于不是最底层的非终端节点,则将别比key小的最大值替换key
            BTreeNode q = p.childs[index - 1];
            while(q.childs[0] != null){
                q = q.childs[q.keyNum];
            }
            p.keys[index] = q.keys[q.keyNum];
            delete(q,q.keys[q.keyNum]);
        }
    }
    public static void delete(BTreeNode p,int key){
        if(p.keyNum >= MIN_KEY_NUM){
            //删除后节点关键字数满足MIN_KEY_NUM - 1,直接删除
            for(int i = 1; i <= p.keyNum; i ++){
                if(p.keys[i] > key){
                    p.keys[i - 1] = p.keys[i];
                }
            }
            p.keys[p.keyNum] = 0;
            p.keyNum--;
        }else{
            //删除后节点关键字数不能够满足MIN_KEY_NUM - 1,可能需要合并
            int index = 0;
            BTreeNode q = p.parrent;
            if(q == null){
                //p是root,直接删除,因为root至少两棵子树,所以关键字个数没有限制
                for(int i = 1; i <= p.keyNum; i ++){
                    if(p.keys[i] > key){
                        p.keys[i - 1] = p.keys[i];
                    }
                }
                p.keys[p.keyNum] = 0;
                p.keyNum--;
                return;
            }
            for(int i = 0; i <= q.keyNum ; i ++){
                if(q.childs[i] == p){
                    index = i;
                    break;
                }
            }
            //查询右兄弟并且右兄弟的关键字个数大于MIN_KEY_NUM - 1,
            //将父节点中第一个大于key的值移动到删除节点
            //将右兄弟中的最小值替换父节点中的第一个大于key的值
            if(index < q.keyNum && q.childs[index + 1].keyNum >= MIN_KEY_NUM){
                for(int i = 0 ; i <= p.keyNum ; i ++){
                    if(p.keys[i] > key){
                        p.keys[i - 1] = p.keys[i];
                    }
                }
                p.keys[p.keyNum] = q.keys[index + 1];
                q.keys[index + 1] = q.childs[index + 1].keys[1];
                for(int i = 2; i <= q.childs[index + 1].keyNum ; i ++){
                    q.childs[index + 1].keys[i - 1] = q.childs[index + 1].keys[i];
                }
                q.childs[index + 1].keys[q.childs[index + 1].keyNum] = 0;
                q.childs[index + 1].keyNum--;
                return;
            }
            //查询左兄弟并且左兄弟的关键字个数大于MIN_KEY_NUM - 1
            //将父节点中最后一个小于key的值移动到删除节点
            //将左兄弟中的最大值替换父节点中的最后一个小于key的值
            if(index > 0 && q.childs[index - 1].keyNum >= MIN_KEY_NUM){

                for(int i = p.keyNum ; i >= 1  ; i --){
                    if(p.keys[i] < key){
                        p.keys[i + 1] = p.keys[i];
                    }
                }
                p.keys[1] = q.keys[index];
                q.keys[index] = q.childs[index - 1].keys[q.childs[index - 1].keyNum];
                q.childs[index - 1].keys[q.childs[index - 1].keyNum] = 0;
                q.childs[index - 1].keyNum--;
                return;
            }

            //不符合上述条件,则需要有merge操作
            //删除key,然后和兄弟合并
            for(int i = 1 ; i < p.keyNum; i++){
                if(p.keys[i] > key){
                    p.keys[i - 1] = p.keys[i];
                }
            }
            //将最后一个值赋值为0
            p.keys[p.keyNum] = 0;
            p.keyNum--;
            if(index < q.keyNum){
                //将节点与右节点结合
                merge(p,true);
            }else{
                //将节点与左节点结合
                merge(p,false);
            }
        }   
    }
    public static void merge(BTreeNode p,boolean flag){
        BTreeNode q = p.parrent;
        int index = 0;
        for(int i = 0; i <= q.keyNum ; i++){
            if(q.childs[i] == p){
                index = i;
            }
        }
        if(flag){
            //将节点与右节点结合
            BTreeNode br = q.childs[index + 1];
            //System.out.print("br.keyNum:" + br.keyNum);
            //System.out.println("\t\t\t" + Arrays.toString(br.keys));
            p.keys[++p.keyNum] = q.keys[index + 1];

            for(int i = index + 1; i <= q.keyNum; i++){
                q.keys[i] = q.keys[i + 1];
                q.childs[i] = q.childs[i + 1];
            }
            q.keyNum --;
            //if(br.keyNum > 0){
                System.arraycopy(br.keys,1,p.keys,p.keyNum + 1,br.keyNum);
                System.arraycopy(br.childs,0,p.childs,p.keyNum,br.keyNum + 1);
                p.keyNum += br.keyNum;
            //}

            if(q == root){
                if(q.keyNum == 0){
                    root = p;
                    p.parrent = null;
                    for(int i = 0; i <= p.keyNum; i ++){
                        if(p.childs[i] != null){
                            p.childs[i].parrent = root;
                        }
                    }
                }
            }else{
                if(q.keyNum < MIN_KEY_NUM - 1){
                    BTreeNode q1 = q.parrent;
                    int index1 = 0;
                    for(int i = 0; i <= q1.keyNum ; i++){
                        if(q1.childs[i] == q){
                            index1 = i;
                        }
                    }
                    if(index1 < q1.keyNum){
                        merge(q,true);
                    }else{
                        merge(q,false);
                    }
                }
            }
        }else{
            //将节点与左节点结合
            BTreeNode lr = q.childs[index - 1];
            merge(lr,true);
        }
    }
    public static void printBTree(){
        Queue<BTreeNode> queue = new LinkedList<BTreeNode>();
        queue.offer(root);
        while(!queue.isEmpty()){
            BTreeNode tmp = queue.poll();
            if(tmp != null ){
                System.out.print("keyNum:" + tmp.keyNum);
                System.out.print("\t\t" + Arrays.toString(tmp.keys));
                System.out.println("\t\t\t\t" + tmp.parrent + "------" + tmp);
                //System.out.print("\t\t\t\t" + tmp);
                //System.out.println("\t\t\t\t\t\t" + tmp.parrent);
                for(int i = 0 ; i <= tmp.keyNum; i++){
                    queue.offer(tmp.childs[i]);
                }
            }
        }
    }
    static class BTreeNode
    {
        //指向父节点指针
        public BTreeNode parrent;
        //本节点的关键字个数
        public int keyNum;
        //关键字数组,最多M-1个关键字,0号元素不用,1个作为备用
        public int[] keys = new int[M + 1];
        //子树指针,最多M棵子树
        public BTreeNode[] childs = new BTreeNode[M + 1];
    }
}

Trie

字典树

import java.util.*;

/* * 字典树 * 1. 统计词频 * 2. 字符串排序 * 3. 最长公共前缀 */

public class Trie {
    private TrieNode root;

    public Trie() {
        root = new TrieNode();
    }

    public static void main(String[] args) 
    {
        System.out.println("Hello World!");
    }

    // Inserts a word into the trie.
    public void insert(String word) {
        TrieNode p = root;
        for(int i = 0; i < word.length();i++){
            char c = word.charAt(i);
            if(p.nodes[c-'a'] == null){
                TrieNode tmp = new TrieNode(c);
                p.nodes[c - 'a'] = tmp;
                p = tmp;
            }else{
                p = p.nodes[c-'a'];
            }
        }
        p.flag = 1;
    }

    // Returns if the word is in the trie.
    public boolean search(String word) {
        TrieNode p = root;
        for(int i = 0; i < word.length();i++){
            char c = word.charAt(i);
            if(p.nodes[c-'a'] == null){
                return false;
            }else{
                p = p.nodes[c-'a'];
            }
        }
        if(p.flag == 1){
            return true;
        }else{
            return false;
        }

    }

    // Returns if there is any word in the trie
    // that starts with the given prefix.
    public boolean startsWith(String prefix) {
        TrieNode p = root;
        for(int i = 0; i < prefix.length();i++){
            char c = prefix.charAt(i);
            if(p.nodes[c-'a'] == null){
                return false;
            }else{
                p = p.nodes[c-'a'];
            }
        }
        return true;
    }
}
class TrieNode {
    // Initialize your data structure here.
    public char key;
    public TrieNode[] nodes;
    //flag == 1 表示是字符串
    //flag == 0 表示是前缀
    public int flag;
    //public int count;统计词频
    public TrieNode() {
        key='\0';
        nodes = new TrieNode[26];
    }
    public TrieNode(char c){
        key = c;
        nodes = new TrieNode[26];
        flag = 0;
    }
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/havedream_one/article/details/47340263
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞