読者の皆さん、こんばんは。これらのブログでは、アルゴリズムの検索を順次紹介しています。このブログで紹介されているシンボルテーブルの検索アルゴリズムは段階的です。前の方法の欠点のため、後者の方法を使用して改善します。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.二分法は静的データを対象としています。
このデータが動的である場合、新しいデータが継続的に書き込まれます。順序をどのように保証しますか?並べ替えを続けますか?つまり、二分法は、新しいデータが常に挿入される状況に対処できません。
そのため、二分探索木が誕生し、次のブログが再会します〜