博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
查找算法总结(二分查找/二叉查找树/红黑树/散列表)
阅读量:6293 次
发布时间:2019-06-22

本文共 6215 字,大约阅读时间需要 20 分钟。

1、二分查找

  二分查找时,先将被查找的键和子数组的中间键比较。如果被查找的键小于中间键,就在左子数组继续查找,如果大于中间键,就在右子数组中查找,否则中间键就是要找的元素。

/** * 二分查找 */public class BinarySearch {    public static int find(int[] array, int key) {        int left = 0;        int right = array.length - 1;        // while (left <= right)不能改为<,否则的话条件判断不完整        while (left <= right) {            int mid = left + (right - left) / 2;            if (key == array[mid]) {                return mid;            } else if (key < array[mid]){                right = mid - 1;            } else {                left = mid + 1;            }        }        return -1;    }}

  每次移动left和right指针的时候,需要在mid的基础上+1或者-1, 防止出现死循环, 程序也就能够正确的运行。

  但如果条件稍微变化一下,你还会写吗?如,数组之中的数据可能可以重复,要求返回匹配的数据的最小(或最大)的下标;更近一步, 需要找出数组中第一个大于key的元素(也就是最小的大于key的元素的)下标,等等。 这些,虽然只有一点点的变化,实现的时候确实要更加的细心。这些二分检索变种的实现见:/

2、二叉查找树

  二叉查找树对于树中的每个节点x,它的左子树所有关键字小于X的关键字,而它的右子树中所有关键字大于X的关键字。

  二叉查找树主要操作是查找和插入,其流程如下图所示:

 

二叉查找树节点类如下:

/** * 二叉查找树节点类 */class Node {    // ----------------------------------- Instance Variables    public Node left;    public Node right;    public int data;}

二叉查找树类代码如下:

/** * 二叉查找树类 */public class BinaryTree {    // ----------------------------------- Instance Variables    public Node root;  // 根节点    public int  nodes; // 节点个数    // ----------------------------------- Constructors    public BinaryTree() {        root = null;        nodes = 0;    }    // ----------------------------------- Public Methods    public void insert(int data) {        root = insertInternal(root, data);    }    public void remove(int data) {        if (find(data) != null) {            root = removeInternal(root, data);            nodes--;        }    }    public Node find(int key) {        Node node = root;        while (node != null) {            if (key == node.data) {                return node;            } else if (key < node.data) {                node = node.left;            } else {                node = node.right;            }        }        return null;    }    public Node min() {        if (root == null) {            return null;        }        Node node = root;        while (node.left != null) {            node = node.left;        }        return node;    }    public Node max() {        if (root == null) {            return null;        }        Node node = root;        while (node.right != null) {            node = node.right;        }        return node;    }    @Override    public String toString() {        if (root != null) {            StringBuilder buff = new StringBuilder();            toStringInternal(root, buff);            return buff.toString();        }        return "";    }    // ----------------------------------- Private Methods    private Node newNode(int data) {        Node node = new Node();        node.data = data;        node.left = node.right = null;        return node;    }    private void toStringInternal(Node node, StringBuilder buff) {        if (node != null) {            toStringInternal(node.left, buff);            buff.append(node.data + " ");            toStringInternal(node.right, buff);        }    }    private Node insertInternal(Node node, int data) {        if (node == null) {            node = newNode(data);            nodes++;        } else if (data < node.data) {            node.left = insertInternal(node.left, data);        } else if (data > node.data) {            node.right = insertInternal(node.right, data);        }        return node;    }    private Node removeInternal(Node node, int data) {        if (node == null) {            return null;        } else if (data < node.data) {            node.left = removeInternal(node.left, data);        } else if (data > node.data) {            node.right = removeInternal(node.right, data);        } else if (node.left != null && node.right != null) {            Node tmp = min(node.right);            node.data = tmp.data;            node.right = removeInternal(node.right, tmp.data);        } else { // 删除节点有一个child节点或者没有child节点            if (node.left != null) {                node = node.left;            } else if (node.right != null) {                node = node.right;            } else {                node = null;            }        }        return node;    }    private Node min(Node node) {        if (node == null) {            return null;        }        while (node.left != null) {            node = node.left;        }        return node;    }}

  以上是二叉查找树的代码实现,还有一种平衡查找树是AVL树,和二叉查找树类似。一颗AVL树是其每个节点的左子树和右子树的高度最多差1的二叉查找树。(假设空树的高度定义为0)。AVL树具体请查看。

3、红黑树

  红黑树是平衡树的一种,保证最坏情况下操作时间复杂度为O(lgo(n))。红黑树的应用比较广泛,比如作为C++中STL的set和map的底层数据结构,Java集合中TreeSet和TreeMap的底层数据结构等。学习红黑树,可以把二叉查找树作为参考,这样有助于加深理解。红黑树的操作主要包括节点旋转、插入、删除等操作。

  红黑树讲解和实现请点击:

4、散列表

  散列是一种用于以常数平均时间执行插入、删除和查找的技术。理想的散列数据结构只不过是一个包含有关键字的具有固定大小的数组。典型情况下,一个关键字就是一个带有相关值(工资信息等)的字符串。

    散列函数主要的问题就是解决冲突的消除问题。如果当一个元素被插入时另一个元素已经存在(散列值存在),那么就会产生冲突。解决这种冲突的方法有几种,一般用最简单的两种:分离链接法、开放地址法。

哈希表类代码如下:

/** * 哈希表类 */public class Hashlist {    // ----------------------------------- Instance Variables    private List
> array; private int capacity; // 哈希表大小 // ----------------------------------- Constructors public Hashlist() { this(47); } public Hashlist(int capacity) { this.capacity = capacity; if (capacity < 47) { this.capacity = 47; } array = new ArrayList
>(); for (int i = 0; i < capacity; i++) { array.add(new ArrayList
()); } } // ----------------------------------- Public Methods public boolean find(int data) { int index = hash(data); List
list = array.get(index); if (list.contains(data)) { return true; } return false; } public void insert(int data) { int index = hash(data); List
list = array.get(index); if (!list.contains(data)) { list.add(data); } } @Override public String toString() { StringBuilder buff = new StringBuilder(); for (int i = 0; i < array.size(); i++) { List
list = array.get(i); buff.append(i + ": "); buff.append(list + "\n"); } return buff.toString(); } // ----------------------------------- Private Methods public int hash(int data) { return (data % capacity); }}

 

 参考资料:

  1、/

转载地址:http://fhdta.baihongyu.com/

你可能感兴趣的文章
PHP中常见的面试题2(附答案)
查看>>
26.Azure备份服务器(下)
查看>>
mybatis学习
查看>>
LCD的接口类型详解
查看>>
Spring Boot Unregistering JMX-exposed beans on shutdown
查看>>
poi 导入导出的api说明(大全)
查看>>
Mono for Android 优势与劣势
查看>>
将图片转成base64字符串并在JSP页面显示的Java代码
查看>>
js 面试题
查看>>
sqoop数据迁移(基于Hadoop和关系数据库服务器之间传送数据)
查看>>
腾讯云下安装 nodejs + 实现 Nginx 反向代理
查看>>
Javascript 中的 Array 操作
查看>>
java中包容易出现的错误及权限问题
查看>>
AngularJS之初级Route【一】(六)
查看>>
服务器硬件问题整理的一点总结
查看>>
SAP S/4HANA Cloud: Revolutionizing the Next Generation of Cloud ERP
查看>>
Mellanox公司计划利用系统芯片提升存储产品速度
查看>>
白帽子守护网络安全,高薪酬成大学生就业首选!
查看>>
ARM想将芯片装进人类大脑 降低能耗是一大挑战
查看>>
Oracle数据库的备份方法
查看>>