一般的なグラフィカルな高速検索アルゴリズム

検索

検索アルゴリズムは、プロジェクトコレクションの過程で特定のアイテムを見つけることです。プロジェクトが存在する場合ので、いつもの答えは、trueまたはfalseです検索します。いくつかの一般的な検索方法:シーケンシャル検索、バイナリ検索、バイナリ検索、ハッシュ・ルックアップ

バイナリ検索

また、バイナリサーチバイナリ検索、比較の少数の利点として知られている高速を見つけ、平均的なパフォーマンス;欠点は、ルックアップテーブルを注文するための必要条件である、および削除の困難を挿入します。したがって、二分探索法は、頻繁に変更し、頻繁に順序付きリストを見つけることができませんに適用可能です。両者が等しい場合は、最初、表要素が昇順であることを前提とし、検索キーの比較で記録鍵中間位置テーブルが、次いで、ルックアップが成功し、そうでない場合、二つのサブテーブル前後中間位置に記録テーブルの使用、もしキーワード記録の中間位置が検索キーよりも大きい場合、子テーブルの後に子テーブル、またはさらに検索する前にさらに見えます。プロセスは条件が発見されたレコードを満たすまで繰り返され、検索が成功した場合、または子テーブルが存在しなくなるまで、その時点で検索が失敗します。

ここに画像を挿入説明

バイナリ実現を探します

(非再帰)

def binary_search_2(alist,item):
    """二分查找:while版"""
    n = len(alist)
    first = 0
    last = n -1
    while first <= last:
        mid = (first+last) // 2
        if alist[mid] == item:
            return True
        elif item < alist[mid]:
            last = mid - 1
        else:
            first = mid + 1
    return False

(再帰)

def binary_search(alist,item):
    """二分查找:递归版"""
    n = len(alist)
    if n > 0:
        mid = n // 2
        if alist[mid] == item:
            return True
        elif item<alist[mid]:
            return binary_search(alist[:mid],item)
        else:
            return binary_search(alist[mid+1:],item)
    return False

時間複雑

  • 最適な時間の複雑さ: ザ・ 1 O(1)
  • 最悪時間計算量: ザ・ リットル インクルード グラム 2 n個 O(log_2n)

ハッシュ・ルックアップ

ハッシュテーブルは、また、ハッシュ・テーブル(ハッシュ・テーブル)と呼ばれ、この構造は、(キー)キーデータを提供し、その値(値)にマッピングします。長い与えられたキーなどとして、効率的にそれが値に一致した見つけることが可能である時間の複雑近いです ザ・ 1 O(1)
ここに画像を挿入説明
ハッシュテーブルはすぐにそれがキー値、それに応じてマッチ見つける方法ですか?

ハッシュ関数

ハッシュテーブルは、本質的に配列です。しかし、唯一の配列の添字に応じて、アクセスにかかるAの方法[2]、[3]、[4]、[1]、[0]のように、キーハッシュは、ベース文字列型に基づいていますA。

例えば、学生がキーとして番号を学び、ジョン・ドウに002123の問い合わせを入力し、またはキー、問い合わせ・デジタル46による入力のための言葉......

だから我々は「通過点」を必要とし、キー配列は、いくつかの方法で変換すること添字。トランジット・ステーションは、ハッシュ関数と呼ばれています。
ここに画像を挿入説明
このいわゆるハッシュ関数は、それを実現する方法ですか?異なる言語では、ハッシュ関数の実装は同じではありません。ここではPythonの辞書(辞書)に、例えば、Pythonでハッシュ関数を達成するために見てみましょう。

Pythonとほとんどのオブジェクト指向言語では、すべてのオブジェクトは、独自のハッシュコードを持って、ハッシュコードは、識別の異なるオブジェクトを区別することが重要です。オブジェクト自体の種類に関係なく、そのハッシュコードは整数の変数であるということです。彼らは、整数の変数なので、あなたは、配列のインデックスに変換したい本当来ることは難しいことではありません。それが何であるかを変換する最も簡単な方法は何ですか?これは、配列の長さに応じてモジュロ演算です。

インデックス=ハッシュコード(キー)%Array.lengthと

ハッシュ関数によって、我々は文字列またはキーの他の種類を置くことができ、配列の添字インデックスに変換されます。

アレイ8は、キー= 001121、所定の長さ

インデックス=ハッシュコード( "001121")%Array.lengthと= 1420036703% 8 = 7
キーはこれを=場合は、
インデックス=ハッシュコード( "本")%Array.lengthと= 3559070パーセント8 = 6

読み取りおよび書き込み操作の辞書

ハッシュ関数を使用すると、読むことができますし、辞書に書きます。

1.書き込み動作

書き込み新しいキーが(辞書パイソンを使用して)のハッシュテーブルに挿入されています。コールのdict =:キーを意味{「002931」「王ウーは」}、002931、値の王5ペアが挿入されています。具体的にどのようにそれを行うには?

第1步,通过哈希函数,把Key转化成数组下标5。
第2步,如果数组下标5对应的位置没有元素,就把这个dict填充到数组下标5的位置。
ここに画像を挿入説明
但是,由于数组的长度是有限的,当插入的dict越来越多时,不同的Key通过哈希函数获得的下标有可能是相同的。例如002936这个Key对应的数组下标是2;002947这个Key对应的数组下标也是2。
ここに画像を挿入説明
这种情况,就叫作哈希冲突。

哈希冲突是无法避免的,既然不能避免,我们就要想办法来解决。解决哈希冲突的方法主要有两种,一种是开放寻址法,一种是链表法。

开放寻址法的原理很简单,当一个Key通过哈希函数获得对应的数组下标已被占用时,我们可以“另谋高就”,寻找下一个空档位置。
以上面的情况为例,dict6通过哈希函数得到下标2,该下标在数组中已经有了其他元素,那么就向后移动1位,看看数组下标3的位置是否有空。
ここに画像を挿入説明
很不巧,下标3也已经被占用,那么就再向后移动1位,看看数组下标4的位置是否有空。
ここに画像を挿入説明
幸运的是,数组下标4的位置还没有被占用,因此把Entry6存入数组下标4的位置。
ここに画像を挿入説明
这就是开放寻址法的基本思路。当然,在遇到哈希冲突时,寻址方式有很多种,并不一定只是简单地寻找当前元素的后一个元素,这里只是举一个简单的示例而已。

在python中就是采用的开放定址法来解决冲突,开放定址法也称为闭散列法.当产生冲突时,python会通过一个二次探测函数f,计算下一个候选索引, 如果索引不可用,就再次用f探测.直到找到一个可用的位置.

之所以叫做闭散列法,就是因为冲突的元素没有开辟额外的存储空间,还是在原先hash表的空间范围之内。

2.读操作
讲完了写操作,我们再来讲一讲读操作。读操作就是通过给定的Key,在散列表中查找对应的Value。

例如调用 dict.get(“002936”),意思是查找Key为002936的dcit在散列表中所对应的值。

3. 扩容
在讲解数组时,曾经介绍过数组的扩容。既然散列表是基于数组实现的,那么散列表也要涉及扩容的问题。

首先,什么时候需要进行扩容呢?

当经过多次元素插入,散列表达到一定饱和度时,Key映射位置发生冲突的概率会逐渐提高。这样一来,大量元素拥挤在相同的数组下标位置,形成很长的链表,对后续插入操作和查询操作的性能都有很大影响。
ここに画像を挿入説明
这时,散列表就需要扩展它的长度,也就是进行扩容。

对于python中的散列表实现dict来说,影响其扩容的因素有两个。

  • Capacity,即散列表的当前长度
  • LoadFactor,即散列表的填装因子,默认值为0.75f

散列表的填装因子很容易计算。
ここに画像を挿入説明
散列表使用数组来存储数据,因此你需要计算数组中被占用的位置数。例如,下述散列表的填装因子为2/5,即0.4。
ここに画像を挿入説明
填装因子大于1意味着被占用元素的数量超过了数组的长度。一旦填装因子开始增大,你就需要在散列表中添加位置,这被称为调整长度。

以上就是散列表各种基本操作的原理。由于dict的实现代码相对比较复杂,这里就不直接列出源码了,有兴趣的读者可以在python中直接阅读PyDictObject对象的源码。

二叉树查找

二叉查找树(binary search tree)在二叉树的基础上增加了以下几个条件。

  • 如果左子树不为空,则左子树上所有节点的值均小于根节点的值
  • 如果右子树不为空,则右子树上所有节点的值均大于根节点的值
  • 左、右子树也都是二叉查找树

下图就是一个标准的二叉查找树。
ここに画像を挿入説明
二叉查找树的这些条件有什么用呢?当然是为了查找方便。

例如查找值为4的节点,步骤如下。

  1. 访问根节点6,发现4<6。
    ここに画像を挿入説明
  2. 访问节点6的左孩子节点3,发现4>3。
    ここに画像を挿入説明
  3. アクセス4 = 4ことが見出さ右の子ノード3、ノード4、発見するノード。
    ここに画像を挿入説明
    ノードの合計数がnである場合は二分探索木の比較的バランスのとれた分配ノードについては、その後、探索ノードの時間複雑さは、深さO(LOGN)であり、ツリーは同じです。

それは徐々に見つける大きさの比較に依存している、とバイナリ検索アルゴリズムは非常に似ています。

公開された29元の記事 ウォンの賞賛8 ビュー9201

おすすめ

転載: blog.csdn.net/qq_35289736/article/details/104100388