アルゴリズム順序付けされていないリンクリストでの5次検索、順序付けされた配列でのバイナリ検索

読者の皆さん、こんばんは。これらのブログでは、アルゴリズムの検索を順次紹介しています。このブログで紹介されているシンボルテーブルの検索アルゴリズムは段階的です。前の方法の欠点のため、後者の方法を使用して改善します。2つの方法が満足のいくものではない場合は、突破して新しいデータ構造を見つける必要があります。

このブログのコード例は次のとおりです。Algorithm Algorithm Forth Edition
[US] Robert Sedgewick Kevin Wayne by Xie Luyun

1.順序付けされていないリンクリストでの検索の順序付け

package com.cmh.algorithm;

/**
 * @author: 起舞的日子
 * @date: 2020/4/6 下午11:24
 * 符号表:基于无序链表的顺序查找
 * ST = Symbol Table
 */
public class SequentialSearchST<Key, Value> {

    private Node first;//链表首节点

    private class Node {
        //链表节点定义
        Key key;
        Value value;
        Node next;

        public Node(Key key, Value value, Node next) {
            this.key = key;
            this.value = value;
            this.next = next;
        }
    }

    public Value get(Key key) {
        //根据给定的键返回对应的值
        for (Node x = first; x != null; x = x.next) {
            if (key.equals(x.key)) {
                return x.value;//命中  如果key是对象,要考虑对象对象等价性
            }
        }
        return null;//未命中
    }

    public void put(Key key, Value val) {
        //根据给定的键,找到则更新其值,否则在表中新建节点
        for (Node x = first; x != null; x = x.next) {
            if (key.equals(x.key)) {
                x.value = val;
                return;
            } else {
                first = new Node(key, val, first); //未命中,新建节点p
            }
        }
    }

    /**
     * 使用无序链表实现K,V查找和插入,最大问题是数据量很大时候,算法复杂度至少在O(N)级别,
     * 算法消耗在:比较的次数上
     */
}

第2に、順序付けされていないリンクリストでの順次検索

package com.cmh.algorithm;

import edu.princeton.cs.algs4.Queue;

import static edu.princeton.cs.algs4.BinaryStdIn.isEmpty;

/**
 * @author: 起舞的日子
 * @date: 2020/4/6 下午11:40
 * 符号表:基于有序数组的二分查找
 */
public class BinarySearchST<Key extends Comparable<Key>, Value> {
    private Key[] keys;
    private Value[] vals;
    private int N;

    public BinarySearchST(int capacity) {
        //调整数组大小... 省略
        keys = (Key[]) new Comparable[capacity];
        vals = (Value[]) new Object[capacity];
    }

    public int size() {
        return N;
    }

    public Value get(Key key) {
        if (isEmpty()) {
            return null;
        } else {
            int i = rank(key);
            if (i < N && keys[i].compareTo(key) == 0) {
                return vals[i];
            } else {
                return null;
            }
        }
    }

    //基于有序数组的二分查找(无递归调用)
    public int rank(Key key) {
        int lo = 0, hi = N - 1;
        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;
            int cmp = key.compareTo(keys[mid]);
            if (cmp < 0) {
                hi = mid - 1;
            } else if (cmp > 0) {
                lo = mid + 1;
            } else {
                return mid;
            }
        }
        return lo;
    }

    /**
     * 还可以用递归方式实现二分查找
     */
    public int rank(Key key, int lo, int hi) {
        if (hi < lo) {
            return lo;
        }
        int mid = lo + (hi - lo) / 2;
        int cmp = key.compareTo(keys[mid]);
        if (cmp < 0) {
            return rank(key, lo, mid - 1);
        } else if (cmp > 0) {
            return rank(key, mid + 1, hi);
        } else {
            return mid;
        }
    }

    public void put(Key key, Value val) {
        //查找键,找到则更新值,否则创建新元素
        int i = rank(key);
        if (i < N && keys[i].compareTo(key) == 0) {
            vals[i] = val;
            return;
        }
        for (int j = N; j > i; j--) {
            keys[j] = keys[j - 1];
            vals[j] = vals[j - 1];
        }
        keys[i] = key;
        vals[i] = val;
    }

    public Key min() {
        return keys[0];
    }

    public Key max() {
        return keys[N - 1];
    }

    public Key select(int k) {
        return keys[k];
    }

    public Key ceiling(Key key) {
        int i = rank(key);
        return keys[i];
    }

    public Iterable<Key> kes(Key lo, Key hi) {
        Queue<Key> q = new Queue<>();
        for (int i = rank(lo); i < rank(hi); i++) {
            q.enqueue(keys[i]);

        }
/*
        if(contains(hi)){
            q.enqueue(keys[rank(hi)]);

        }
*/
        return q;
    }
    /**
     * 总结:
     * 二分查找优点:
     * 1、查找算法复杂度是对数log级别的
     *
     * 缺点:
     * 1、数据需有序;
     * 2、把很大量的数据排序在很多情况下复杂度会大大提升;
     * 3、有些数据查找和插入是混合进行的,排序好的静态数据就不合适;
     *
     *
     * 所以需要一种新的数据结构,可以结合二分查找的优缺点:
     * 二叉查找树
     * 1)可以用二分法快速查找;
     * 2)可以类似链表快速插入
     * 下一篇博客介绍
     */
}

3.まとめ

二分法を使用して数を推測することで、100以内の整数を7回推測するだけでよいことがわかります。大きな数であっても、推測の数はそれほどひどくありません。私が検索時に知っている限り、二分法よりも速くはありません。の

しかし、世界がこんなにシンプルだったらいいのに。
1.二分法が効率的であるための前提条件は、データを順序付けする必要がある
ことです。100の不要な整数が与えられた場合、何を推測しますか?データを効率的に並べ替えるには、多くの従来の並べ替えアルゴリズムが必要であり、すばやく見つけることができます。大量のデータがあるため、世界は複雑です。1は大量です。2は、並べ替えに費やすエネルギーが、並べ替えを行うよりも優れていないためです。

2.二分法は静的データを対象としています。
このデータが動的である場合、新しいデータが継続的に書き込まれます。順序をどのように保証しますか?並べ替えを続けますか?つまり、二分法は、新しいデータが常に挿入される状況に対処できません。

そのため、二分探索木が誕生し、次のブログが再会します〜

元の記事を181件公開 賞賛された66件 20万回の閲覧

おすすめ

転載: blog.csdn.net/meiceatcsdn/article/details/105355075