【数据结构】查找算法

1.查找算法概述:

  • 顺序查找
  • 二分查找
  • 分块查找
  • 二叉排序树查找
  • 哈希表查找

2.顺序查找:
java实现:

public int seqSearch(int[] data, int key){
        int index;
        for(index = 0; index < data.length; index++){
            if(key == data[index]){
                return index;
            }
        }
        return -1;
    }

3.二分查找:
java实现:

public int binSearch(int[] data, int key){
        int low = 0, high = data.length - 1, mid;
        while (high >= low){
            mid = (low + high) / 2;
            if(key == data[mid]){
                return mid;
            }
            else if(key > data[mid]){
                low = mid + 1;
            }else {
                high = mid - 1;
            }
        }
        return -1;
    }

4.分块查找:
java实现:

static class BlockInfo{
        int blockBeginIndex; //块的起始下标
        int blockEndIndex;   //块的结束下标
        int blockMaxValue;   //块中最大关键字
    }
    public int blockSearch(int[] data, int key){
        BlockInfo[] blocks = getBlockArray(data);
        int blockindex = -1;
        for(int i = 0; i < blocks.length - 1; i++){
            if(key >= blocks[i].blockMaxValue && key <= blocks[i + 1].blockMaxValue){
                blockindex = i + 1;
                break;
            }
        }
        if(blockindex != -1){
            int index;
            for(index = blocks[blockindex].blockBeginIndex; index < blocks[blockindex].blockEndIndex; index++){
                if(key == data[index]){
                    return index;
                }
            }
        }
        return -1;
    }
    //创建分块查找的索引表
    private BlockInfo[] getBlockArray(int[] data) {
        int length = data.length;
        int n = (int)Math.sqrt(length);
        int m = (int)length / n;
        BlockInfo[] blocks = new BlockInfo[m];
        for(int i = 0; i < m; i++){
            BlockInfo block = new BlockInfo();
            block.blockBeginIndex = i * n;
            if(i * n + n - 1 < length -1){
                block.blockEndIndex = i * n + n -1;
            }else {
                block.blockEndIndex = length - 1;
            }
            int maxValue = data[block.blockBeginIndex];
            for(int j = block.blockBeginIndex; j < block.blockEndIndex; j++){
                if(maxValue < data[j]){
                    maxValue = data[j];
                }
            }
            block.blockMaxValue = maxValue;
            blocks[i] = block;
        }
        return blocks;
    }

5.二叉排序树查找:
java实现:

public class BinarySearchTree {
    //树结点
    private static class TreeNode{
        int key;
        TreeNode left;  //左子树
        TreeNode right;  //右子树
        TreeNode(int key, TreeNode left, TreeNode right){
            this.key = key;
            this.left = left;
            this.right = right;
        }
    }

    private TreeNode root;  //根
    public BinarySearchTree(){
        root = null;
    }
    //树置空
    public void makeEmpty(){
        root = null;
    }
    //判断树是否为空
    public boolean isEmpty(){
        return root == null;
    }
    //是否包含某个元素
    public boolean search(int key){
        return search(key, root);
    }
    public boolean search(int key, TreeNode t){
        if(t == null){
            return false;
        }
        if(key < t.key){
            return search(key, t.left);
        }
        else if(key > t.key){
            return search(key, t.right);
        }
        return true;
    }
    //给树添加一个新的结点
    public void insert(int key){
        root = insert(key, root);
    }
    public TreeNode insert(int key, TreeNode t){
        if(t == null){
            return new TreeNode(key,null, null);
        }
        if(key < t.key){
            t.left = insert(key, t.left);
        }
        else if(key > t.key){
            t.right = insert(key, t.right);
        }
        return t;
    }
    //移除一个结点
    public void remove(int key){
        root = remove(key, root);
    }
    private TreeNode remove(int key, TreeNode t){
        if(t == null){
            return null;
        }
        if(key < t.key){
            t.left = remove(key, t.left);
        }
        else if(key > t.key){
            t.right = remove(key, t.right);
        }
        else if(t.left != null && t.right != null){
            t.key = findMin(t.right).key;
            t.right = remove(t.key, t.right);
        }else {
            t = (t.left != null) ? t.left : t.right;
        }
        return t;
    }
    //查找树中最小值
    public int findMin(){
        if(isEmpty()){
            return Integer.MIN_VALUE;
        }
        return findMin(root).key;
    }
    private TreeNode findMin(TreeNode t){
        if(t == null){
            return null;
        }
        if(t.left == null){
            return t;
        }
        return findMin(t.left);
    }
    //输出树中元素
    public void printTree(){
        if(isEmpty()){
            System.out.println("Empty tree");
        }else {
            printTree(root);
        }
        System.out.println();
    }
    private void printTree(TreeNode t){
        if(t != null){
            printTree(t.left);
            System.out.print(t.key + " ");
            printTree(t.right);
        }
    }
}

测试类:

public class TestBinarySearchTree {
    public static void main(String[] args){
        BinarySearchTree bst = new BinarySearchTree();
        bst.insert(70);
        bst.insert(30);
        bst.insert(40);
        bst.insert(10);
        bst.insert(80);
        bst.insert(20);
        bst.insert(90);
        bst.insert(100);
        bst.insert(75);
        bst.insert(60);
        bst.insert(45);
        System.out.println("遍历二叉排序树");
        bst.printTree();
        System.out.println("hava 80 -->" + bst.search(80));
        System.out.println("hava 65 -->" + bst.search(65));
    }
}

结果:
在这里插入图片描述
6.哈希表查找:

  • 哈希表在关键字和存储位置之间建立了对应关系,理想情况下无须比较关键字就可找到待查关键字,查找的期望时间为O(1).

java实现:

public class HashTableSearch {
    /*哈希结点*/
    private static class Node{
        int key; //链表中的键
        Node next; //下一个同义词
    }

    /*在哈希表中查找关键字key*/
    public boolean HashSearch(int[] data, int key){
        int p = 1;
        //寻找小于或等于最接近表长的素数
        for(int i = data.length; i > 1; i--){
            if(isPrimes(i)){
                p = i;
                break;
            }
        }
        //构建哈希表
        Node[] hashtable = createHashTable(data, p);
        //查找key是否在哈希表中
        int k = key % p;
        Node cur = hashtable[k];
        while (cur != null && cur.key != key){
            cur = cur.next;
        }
        if(cur == null){
            return false;
        }else {
            return true;
        }
    }
    /*用求余,链表法构建哈希表*/
    public Node[] createHashTable(int[] data, int p){
        Node[] hashtable = new Node[p];
        int k; //哈希函数计算的单元地址
        for(int i = 0; i < data.length; i++){
            Node node = new Node();
            node.key = data[i];
            node.next = null;
            k = data[i] % p;
            if(hashtable[k] == null){
                hashtable[k] = node;
            }else {
                Node cur = hashtable[k];
                while (cur.next != null){
                    cur = cur.next;
                }
            }
        }
        return hashtable;
    }
    /*判断是否是一个质数*/
    public boolean isPrimes(int n){
        for(int i = 2; i < Math.sqrt(n); i++){
            if(n % i == 0){
                return false;
            }
        }
        return true;
    }
}

测试:

public class TestHashTableSearch {
    public static void main(String[] args){
        int[] data  = {70, 30, 40, 10, 80, 20, 90, 100, 75, 60, 45};
        HashTableSearch search = new HashTableSearch();
        if(search.HashSearch(data, 80)){
            System.out.println("在数字列表中存在关键字80");
        }else {
            System.out.println("在数字列表中不存在关键字80");
        }
        if(search.HashSearch(data, 65)){
            System.out.println("在数字列表中存在关键字65");
        }else {
            System.out.println("在数字列表中不存在关键字65");
        }
    }
}

结果:
在这里插入图片描述
参考书目:数据结构(Java版)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值