常见的查找算法——二分查找、哈希表、树结构的查找算法

一、 二分查找算法

二分查找是一种高效的查找算法,适用于已排序的数组。它通过将待查找区间不断缩小为一半来查找目标值,直到找到目标值或确定不存在。

二分查找算法代码如下:

public class BinarySearch {
    public static int binarySearch(int[] arr, int target) {
        int left = 0;
        int right = arr.length - 1;

        while (left <= right) {
            int mid = left + (right - left) / 2;

            if (arr[mid] == target) {
                return mid;
            } else if (arr[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }

        return -1;
    }

    public static void main(String[] args) {
        int[] arr = {1, 3, 5, 7, 9, 11, 13, 15};
        int target = 7;
        int result = binarySearch(arr, target);

        if (result != -1) {
            System.out.println("目标值在数组中的索引为:" + result);
        } else {
            System.out.println("目标值不在数组中");
        }
    }
}

二、 哈希表查找算法

哈希表是一种基于哈希函数实现的数据结构,能够快速地查找、插入和删除元素。哈希表通过哈希函数将键映射到存储位置,实现了常数时间复杂度的查找操作。

哈希表查找算法代码如下:

import java.util.HashMap;

public class HashMapSearch {
    public static void main(String[] args) {
        HashMap<String, Integer> hashMap = new HashMap<>();
        hashMap.put("Alice", 25);
        hashMap.put("Bob", 30);
        hashMap.put("Charlie", 35);

        String target = "Bob";
        if (hashMap.containsKey(target)) {
            int age = hashMap.get(target);
            System.out.println(target + "的年龄为:" + age);
        } else {
            System.out.println("未找到对应信息");
        }
    }
}

三、 树结构的查找算法

在树结构中,常用的查找算法包括二叉搜索树查找平衡二叉搜索树(如AVL树、红黑树)查找等。这些算法能够在树结构中快速地查找目标值。

1. 二叉搜索树BST

二叉搜索树是一种二叉树,其中每个节点的值大于其左子树中的所有节点的值,小于其右子树中的所有节点的值。

代码如下:

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    public TreeNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}

public class BinarySearchTree {
    private TreeNode root;

    public BinarySearchTree() {
        this.root = null;
    }

    // 查找操作
    public TreeNode search(int val) {
        return searchRec(root, val);
    }

    private TreeNode searchRec(TreeNode root, int val) {
        if (root == null || root.val == val) {
            return root;
        }

        if (val < root.val) {
            return searchRec(root.left, val);
        } else {
            return searchRec(root.right, val);
        }
    }

    // 插入操作
    public void insert(int val) {
        root = insertRec(root, val);
    }

    private TreeNode insertRec(TreeNode root, int val) {
        if (root == null) {
            return new TreeNode(val);
        }

        if (val < root.val) {
            root.left = insertRec(root.left, val);
        } else if (val > root.val) {
            root.right = insertRec(root.right, val);
        }

        return root;
    }


    public static void main(String[] args) {
        BinarySearchTree bst = new BinarySearchTree();
        bst.insert(5);
        bst.insert(3);
        bst.insert(7);

        TreeNode result = bst.search(3);
        if (result != null) {
            System.out.println("找到节点:" + result.val);
        } else {
            System.out.println("未找到节点");
        }
    }
}

2. AVL树

AVL树是一种自平衡的二叉搜索树,它保持了左右子树的高度差不超过1,从而保持树的平衡。在AVL树中进行查找、插入和删除操作的时间复杂度为O(log n)

AVL树的代码如下:

// AVL树的实现可以使用现有的库,例如Java中的TreeMap和TreeSet等

import java.util.TreeMap;

public class AVLTreeExample {
    public static void main(String[] args) {
        TreeMap<Integer, String> avlTree = new TreeMap<>();
        avlTree.put(5, "apple");
        avlTree.put(3, "banana");
        avlTree.put(7, "orange");

        String result = avlTree.get(3);
        if (result != null) {
            System.out.println("找到节点:" + result);
        } else {
            System.out.println("未找到节点");
        }
    }
}

3. 红黑树

红黑树是一种自平衡的二叉搜索树,它通过在每个节点上添加颜色属性(红色或黑色)来保持平衡。红黑树的特性使得其在插入和删除操作时能够保持树的平衡。
代码如下:

enum Color {
    RED, BLACK
}

class Node {
    int val;
    Color color;
    Node left, right, parent;

    public Node(int val) {
        this.val = val;
        this.color = Color.RED;
        this.left = null;
        this.right = null;
        this.parent = null;
    }
}

public class RedBlackTree {
    private Node root;
    private Node nil;

    public RedBlackTree() {
        nil = new Node(-1);
        nil.color = Color.BLACK;
        root = nil;
    }

    private void leftRotate(Node x) {
        Node y = x.right;
        x.right = y.left;
        if (y.left != nil) {
            y.left.parent = x;
        }
        y.parent = x.parent;
        if (x.parent == nil) {
            root = y;
        } else if (x == x.parent.left) {
            x.parent.left = y;
        } else {
            x.parent.right = y;
        }
        y.left = x;
        x.parent = y;
    }

    private void rightRotate(Node y) {
        Node x = y.left;
        y.left = x.right;
        if (x.right != nil) {
            x.right.parent = y;
        }
        x.parent = y.parent;
        if (y.parent == nil) {
            root = x;
        } else if (y == y.parent.left) {
            y.parent.left = x;
        } else {
            y.parent.right = x;
        }
        x.right = y;
        y.parent = x;
    }

    private void insertFixup(Node z) {
        while (z.parent.color == Color.RED) {
            if (z.parent == z.parent.parent.left) {
                Node y = z.parent.parent.right;
                if (y.color == Color.RED) {
                    z.parent.color = Color.BLACK;
                    y.color = Color.BLACK;
                    z.parent.parent.color = Color.RED;
                    z = z.parent.parent;
                } else {
                    if (z == z.parent.right) {
                        z = z.parent;
                        leftRotate(z);
                    }
                    z.parent.color = Color.BLACK;
                    z.parent.parent.color = Color.RED;
                    rightRotate(z.parent.parent);
                }
            } else {
                Node y = z.parent.parent.left;
                if (y.color == Color.RED) {
                    z.parent.color = Color.BLACK;
                    y.color = Color.BLACK;
                    z.parent.parent.color = Color.RED;
                    z = z.parent.parent;
                } else {
                    if (z == z.parent.left) {
                        z = z.parent;
                        rightRotate(z);
                    }
                    z.parent.color = Color.BLACK;
                    z.parent.parent.color = Color.RED;
                    leftRotate(z.parent.parent);
                }
            }
        }
        root.color = Color.BLACK;
    }

    public void insert(int val) {
        Node z = new Node(val);
        Node y = nil;
        Node x = root;
        while (x != nil) {
            y = x;
            if (z.val < x.val) {
                x = x.left;
            } else {
                x = x.right;
            }
        }
        z.parent = y;
        if (y == nil) {
            root = z;
        } else if (z.val < y.val) {
            y.left = z;
        } else {
            y.right = z;
        }
        z.left = nil;
        z.right = nil;
        z.color = Color.RED;
        insertFixup(z);
    }

   

    public static void main(String[] args) {
        RedBlackTree rbTree = new RedBlackTree();
        rbTree.insert(5);
        rbTree.insert(3);
        rbTree.insert(7);
    }
}

上面代码实现了一个简单的红黑树,包括左旋、右旋和插入修复等操作。

  1. 红黑树的节点定义:
    在代码中,定义了一个节点类 Node ,包含了节点的值 val 、颜色 color 、左子节点 left 、右子节点 right 和父节点 parent 。初始化时,将哨兵节点 nil 定义为黑色,并将根节点 root 初始化为哨兵节点。

  2. 左旋和右旋操作:
    代码中实现了左旋和右旋操作,用于在插入节点后调整红黑树的结构,保持平衡。

  3. 插入修复操作 insertFixup :
    在插入节点后,可能会破坏红黑树的性质,需要通过插入修复操作来修复。插入修复操作主要分为两种情况:

    • Case 1: 当父节点和叔父节点都为红色时,将父节点和叔父节点的颜色修改为黑色,祖父节点的颜色修改为红色,然后将当前节点指向祖父节点,继续修复。
    • Case 2: 当父节点为红色,叔父节点为黑色,并且当前节点是父节点的右子节点时,需要进行左旋操作;当父节点为红色,叔父节点为黑色,并且当前节点是父节点的左子节点时,需要进行右旋操作。
  4. 插入操作 insert :
    在插入节点时,首先找到插入位置,并将新节点的颜色设为红色。然后调用插入修复操作 insertFixup 来修复可能破坏的红黑树性质。

  5. 节点颜色的保证:
    红黑树通过以下规则来保证节点的颜色是红色或黑色:

    • 根节点必须为黑色。
    • 红色节点的子节点必须为黑色。
    • 从根节点到叶子节点的每条路径上,黑色节点的数量必须相同。
    • 不能有两个相邻的红色节点。

通过这些规则,红黑树能够保证节点的颜色是红色或黑色,从而保持树的平衡和性质。这样的设计使得红黑树能够高效地支持插入、删除和查找等操作。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值