「ねえ魏は言った、」データ構造 - ラーニングコンテンツの第VII章のまとめ

 本論文では、基本的なインデックスディレクトリ

 まず、基本的な概念や用語検索

第二に、逐次探索アルゴリズム  

第三に、バイナリサーチアルゴリズム

第四に、バイナリ・ソートツリーアルゴリズム  

V.バランスの取れたバイナリツリーアルゴリズム

六、Bツリーの紹介  

七のハッシュテーブルルックアップ

八例は仕事を表示します

九、反射および自己概要

 

 まず、基本的な概念と用語を探しています:

  (1)検索:値が与えられたが、そのキールックアップテーブルに与えられた値(または記録)に等しいデータ要素を決定します。

  (2)検索アルゴリズムの分類

    1)静的および動的な外観をして下さい。
      注意:すべての用語の静的または動的なルックアップテーブルを。動的テーブルのルックアップテーブルを参照するには、テーブルと、挿入操作を削除しました。

      共通静的テーブル:シーケンシャル検索、バイナリ検索、補間検索、インデックス・ルックアップなど

      共通ダイナミックテーブル:バイナリソートツリー、平衡二分木、Bツリー、ハッシュテーブル

    2)検索し、無秩序な整然とした外観。
      無秩序な検索:列数が秩序 - 無秩序できるで検索。
      注文した検索:列の数が列を注文する必要がありますして下さい。

  (3)平均の長さ(平均検索の長さを、ASL):成功を見つけるために、時間の平均の長さを見つけるための検索アルゴリズムと呼ばれるキーワードの数を、比較行動の重要なニーズと期待を指定します。

  (4)鍵(キー):また、データ要素と識別することができる鍵と呼ばれるデータ要素のデータ項目の値は、です。キーワードは、レコードを一意に識別できる場合は、このキー(主キー)の主キーと呼ばれる、キーワードが複数のレコードに対応している場合、このキーワードは、キーワード(セカンダリキー)と呼ばれています。

 

 

第二に、逐次探索アルゴリズム:

  (1)の定義:シーケンシャル検索(シーケンシャル検索)は、最も基本的な技術を見つけることであるリニアサーチと呼ばれるその発見のプロセスです:テーブルからの最初(または最後)の記録開始、および1つのキーレコードずつ最後の(または最初の)記録されるまで、そのキー値の比較がある与えられた場合、レコードのキーと指定された同じ値が、その後の検索が成功した場合、比較の値が与えられると、調査は、レコードを発見しましたときのように、テーブルには、検索に失敗したレコードをチェックしません。

  

  (2)最も基本的なメソッドを実装します

INT Search_Seq(SSTable ST、キータイプキー)
{ 
    ための式(I = ST.length; I> = 1; - I)
        IF(ST.R [I] .KEY == キー)
            リターンI。 0を返します }

  

  (3)のSentinel実装方法では

// Sentinelはiが範囲外である各周期、すなわちa.length判定を行うよりも小さいガードを必要とせずに、アレイ配列の最後に、[1]キーから順次検索を有しています。
//は私がやるたびにa.lengthと比較する必要はないように見張りを解決することができます設定します。
-1 //説明参照注、失敗した:一つだけ開始は、配列のインデックスから場所を検索する
 int型seqSearchWithGuard(INT [] A、INT キー)
 { 
    int型a.length I = - 1;配列から//設定ループテールが開始
    [0] =キー; //設定[0]である"センチネル"と呼ばれるキー値、
    しばらく([I] =!キー)
        i-- ; 
    IF(I> 0  リターンI;  それ以外の 戻り値-1 ;}

  

  (4)時間計算の推定

  逐次探索アルゴリズムの場合、成功は、複雑さはO(1)であるアルゴリズムの時間を見つけるために、最初の場所で最高の状況を見つけることですシナリオは最後に発見された最悪の場合で、n個の比較を必要とし、時間計算量はO(n)は、n + 1回の比較が必要、時間複雑さが等しい位置に任意のキーワードの確率はO(N)、これにルックアップの平均数(N + 1)/ 2であります最終的な時間計算量はO(N)です。大きなnは、検索効率は、非常に低い場合の方法を見つけるために適用することができるいくつかの小さなデータを探しながら。

 

 

 三、2つの検索アルゴリズム:

  (1)定義:バイナリサーチ(バイナリ検索)、また、バイナリ検索として知られています。線形形式が順次記憶されなければならない、(通常は小から大に順序付け)キーを注文する必要があり、記録線テーブルを前提としています。中間記録に等しいキー値は、検索が成功した場合、順序付きリストでは、比較対象の中間記録として撮影し、値が与えられたキー中間記録、中間未満の場合:バイナリ基本的な考え方は見つけることです値が指定されたキー中間記録よりも大きい場合は、右をし、中間領域の記録に見て、記録された領域は、左を見続けています。レコードが見つからないために、検索が成功するまでのプロセスを繰り返す、または領域の全て、これまでに見つけることができませんでした。

  

  (2)基本的な実装

//バイナリ検索:すべてのデータの配列がない場合、-1を返し、キー配列の添字を含む
INT binarySearch(INT []、INT キー)
{ 
    int型低= 0;最初の記録の最小インデックスの//定義
    INTハイ= a.length-1; //は、最後の最大屈折率を記録定義
    一方(低<= 高)を
    { 
        mIDを=(ハイ+低)をINT / 2; //バイナリ中間記録添字得られる
        (キー場合<a [mid]) //それは
            の間の中間小に調整された高=中間1; //最大インデックスの値よりも小さい値を見つけることができればなら(key> [中間 ])// 場合よりも参照値より大きい大きな中央
            低い=ミッド+ 1; //インデックスが最も低い中間大規模に調整される
            戻りmIDを; //その後、インデックスは中間記録に等しい場合は、実測値である    } 
    を返す-1  }

  

  (3)時間計算の推定

  すなわち、のみが記録半分データの検索結果を見つけるために、二つのサブツリーに分割静的秩序を見つけるに等しいバイナリサーチは、より少ない仕事がバイナリ検索はもちろん、非常に高い効率、継続し、半分に等しいです。

  バイナリツリー4の性質に応じて、すなわち「[+1] Log2nの深さを有するN個のノードのバイナリツリーを完了」、回数キーワードまたはLog2nは[] +1である最悪の場合のルックアップ故障を見つけるためにバイナリサーチすることによって得ることができます最高のコースは、1回なので、二分探索時間の複雑さはOの検索順序よりも明らかにはるかに優れたO(LOGN)、(n)の時間計算のです。

  欠点は、しかし、唯一の順序付けられたシーケンステーブルが記憶される間に、テーブル構造を要求し、ソートし、それ自体をソートする前に必要な見つけることは、動的に線形形状を変化させるには適していない時間のかかる操作です。

 

 

第四に、バイナリ・ソートツリーアルゴリズム:

  (1)定義:また、二分探索木として知られています。これは、空の木や、次の特性を有するバイナリツリーのいずれかです:

      =「左サブツリーそれは、左の部分木の、値空でない場合、すべてのノードがルートの値未満です。

      それは右のサブツリーを空でない場合=」、右の部分木は、ルートノードとその値のすべてのノードの値よりも大きいです。

      =「その左と右のサブツリーもバイナリ・ソートツリーです

      バイナリソートツリーの順序付けられたシーケンスを得るために横断することができる{35,37,47,51,58,62,73,88,93,99}

  

  (2)実装

      探索木が空の場合=」、その後、ルックアップは失敗します。

      =「探索木は、その後、非空の場合:

        ①ルートキーの値に等しい与えられたキー値は、検索は、検索処理の終了に成功した場合、それ以外のターン②

        ②与えられたキー値、キー値は、ルートノードよりも小さい場合は、そうでなければオン、左サブツリーのルートノードに継続される③

        目標は、キー値のルートキーよりも大きい場合③、根ノードの右の部分木に継続されます。

//、検索が偽失敗したリターンで、検索が成功した場合trueを返すバイナリ・ソートツリーpのキーを探す
2のpバイナリ・ソートツリーpがない1つのバイナリ・ソートツリーが空である2つのケースがありますfalseを返します//しかし、空のキー見つけることができませんでした
BOOL searchBSTを(int型はキー){ 
    BiTreeNode現在は= ルートを、
    しばらく(現= nullを!
    { 
        IF(キー==のcurrent.data) trueに復帰 他のIF(キー< current.data)=現在現在.lchild;他に電流= current.rchild;} falseに復帰;}

 

   (3)時間計算の推定

    理想バイナリツリーは、+1 log2N、時間複雑度は、O(LOGN)を探すバイナリサーチに類似[ている]、完全二分木の深さと同じ、比較的バランスが取れています。極端な不均衡の斜ツリーで、時間計算量はO(n)が見つけ、順次検索と同等です。どのようにバランスの取れたバイナリツリーを作るためには、考慮すべき問題となっています。

  

  (4)基本的な動作アルゴリズムバイナリソートツリー

書式#include <stdio.hに>   
する#include <stdlib.h>に含まれ

ます。#define OK 1。
の#define ERROR 0 
TRUEの#define 1。
の#define FALSE 0 
の#defineストレージスペースのMAXSIZE / *初期割り当て* 100 / 

ステータスint型のtypedef; / *ステータス等OK、その結果ステータスコードの関数であり、関数のタイプ、* /である

二分木の/ *バイナリリンクリストノード構造の定義* / 
typedefは構造体BiTNode / *ノード構造* /  {  / *ノードデータ、intデータ* /  構造体BiTNode * lchild、* rchild; / *左の子のポインタ* /  } BiTNode、* BiTree; / *再帰的に検索キーがあるかどうか、* / / *ポインタFポイントTの両親バイナリ・ソート木T、初期NULLの呼び出し* / / *検索が成功した場合、データ要素ノードへのポインタpの指す、とはTRUEを返します* / / *それ以外の場合は、ポインタpの検索パス*上の最後のアクセスノードを指すと返すFALSE / ステータスSearchBST( T BiTree、int型のキー、BiTree F、BiTree * P){(T)は/ *検索が失敗した場合* /!{P * = F;リターンFALSE;}そうでない場合(キー== T->データ)/ * を見つける成功* / {P * = T;返すTRUE;}そうIF(キー<T-> データ)SearchBSTリターン(T-> lchild、キー、 T、P); / * * /他返しSearchBST(T->左部分木を見ていき / *; rchild、キー、T、P) と右のサブツリー*に見える/ } / *ときバイナリ・ソートキーは、キー挿入* / / *、キーデータ要素がツリーT内に存在しないに等しいとTRUEを返し、そうでなければ* FALSE / ステータスInsertBST(BiTree T *、INT キー){BiTree P、S、IF(SearchBST(! * T、キー、NULL、& P))/ * 探索が失敗する* / {S =(BiTree)はmalloc(はsizeof (BiTNode)); S-> =データキー; S-> lchild = S-> rchild = NULL; IF(!= T * S P); / *新しいルートのS * / ELSE IF(キー<p型>挿入データ)のp-> lchild =秒; / *左の子* /他に挿入され、sはP - > rchild = S; / * S * /戻る右の子に挿入されたTRUE;}そうでない場合はfalseを返す;ツリー内の同じノード、無挿入* /内の既存の/ *キーワード} / *次に、両方の左または右の部分木をノードPを削除するバイナリソートツリーから。* / ステータス削除(BiTree * P){BiTree Q、S、IF((Pの*) - > rchild == NULL)/ *単に左サブツリーを再閉路右サブツリーを空に(ノードが削除されます葉はまた、/ *)の枝を取る{;( - ;無料> lchild P *)* P = Q = P * > lchild == NULL)/ *重量のみ- IF((P *;(Q)他)}その右サブツリー* / {Q = P *; * P =(P *) - > rchild;フリー(Q);他} / *左及び右サブツリーは* / nullでないP {* Q =; S = (* P) - > lchild;一方(S-> rchild)/ *左右端を回し* /(探し前駆体はノード削除する){Q = S; S = S-> rchildを;}( * P) - >データ= S- >データ;! / * sの点が即時先行ノードを削除する(値が削除されたノードによって置き換えられます)* / IF(Q削除されたノードの値前駆* = P) Q-> rchild = S-> lchild; / * 再閉路右サブツリーQ * /他Q-> lchild = S-> lchild; / * Qの再閉路は、* /無料サブツリーを左(S);}リターンTRUE;} / *データキーは、ノードは、* / / *、データ要素を削除し、TRUEを返し、バイナリソートツリーTが存在するの重要な要素が等しい場合、そうでない場合はFALSEを返します。* / ステータスDeleteBST(BiTree * T、int型キー){(* T!場合 )/ * キーは、キーデータ要素に等しい* /リターン不在FALSE;他{IF(キー==(* T) - >データ)/ *キーは、キーデータ要素を等しい見つけます* /戻るの削除(T)を、そうでないIF(キー<(* T) - > データ)を返すDeleteBST(&(* T) - > lchild、キー);それ以外を返すDeleteBST(&(* T) - > rchild、キー);}} int型メイン(ボイド){int型I、INT A [10] = {62,88,58,47,35,73,51,99,37,93 }; BiTree T = NULL;のための(I = 0;私は10 <; I ++の)InsertBST(&T、A [I]); DeleteBST(&T、93 ); DeleteBST(&T、47 ); 0を返します;}

 

 

 V.バランスの取れたバイナリツリーアルゴリズム:

  (1)に定義されます

    平衡二分木(自己均衡バイナリ検索ツリーまたは高バランスバイナリ検索ツリー)、バイナリソートツリー、請求項1に等しい左ノードのサブツリー、および多くとも右サブツリーの各々の高さの差。平衡二分木は空のツリー、またはその左サブツリー及び右サブツリーさ平衡二分木、左サブツリー及び右サブツリーの深さとの間の絶対差のいずれかである高度にバランスバイナリソート木、あります値が1を超えてはなりません。右の部分木の深さを差し引いたノードバイナリツリーの深さ値の左サブツリーがバランス係数BF(バランス因子)と呼ばれ、その後、平衡二分木のすべてのノードのみ-1、0及び1の係数によってバランスされてもよいです。最近挿入ノード、及びバランス係数から最小不平衡ツリーと呼ばれるサブツリーのルートノードの絶対値よりも大きいです。

   (2)基本的なアルゴリズム

   (このブロックは、完全に記事を読んで、その後出て仕上げ完了するまでにはもう少し時間が無視され、調整のバランスれます)

 

 

六、Bツリーの説明:

  (1)背景

      上述した検索アルゴリズムをメモリに行われ、彼らは、より小さなファイルのために適切であるが、大きいため、外部メモリに格納されたファイルであってもで、このような大規模なファイルのため、不適切ですバランスの取れたバイナリツリー、検索効率にまだ低いです。

      非常に大きな、大きなメモリを動作するように設定データを扱うための方法がない場合は、この場合には、データの処理は、常にメモリページを呼び出すためにハードディスクなどの記憶装置から転送する必要があります。それは、このような外部デバイスになると、時間に関して複雑さを計算することだけでなく、機能はその要素が外部記憶装置のハードディスクのアクセス時間のために考慮されなければならない比較の必要な数を見つけるためにしている要素のコレクションに、アクセスの時間を変更しますそして何回個々のアクセスは、デバイスに行われます。

   (2)が定義されています

      ツリーの前にノードが複数の子を持つことができるが、それ自身の店舗だけ一つの要素、より制限バイナリツリーは、ノードが2つだけの子供の最大値を有することができます。ノードは、要素が非常に多くの時間である、要素を格納することができるので、非常に大きいまたはツリーの(サブツリーは、ノードの最大数を有する)、またはツリーの高さが非常に大きい、あるいは両方が必要十分な大きさ。これは、メモリの非常に大きな数は、したがって、我々は、各ノードが格納制限の唯一の要素を分割する必要があり、時間効率上のボトルネックになった明らかにされた外部メモリにアクセスすることができます。

      子ノードツリーは、2つ以上であってもよいし、各ノードで複数の要素を格納することができるそれぞれが複数の検索ツリー(muitiウェイ探索木)。

   (3)のB +ツリーのアップグレードバージョンを定義します

      B +ツリーのツリーは、Bツリーにおいて異なるBツリーの変形例です。

    • そこノードkサブノードは、鍵Kを持っている必要があります。
    • レコードに関する情報は、リーフノードに格納された非リーフノードは、インデックスの唯一の役割を担っています。
    • ソートされたリンクリストを構成する木のすべてのリーフノードは、ソート済みキーの順序ですべてのレコードを横断することができます。

      

         以下、図との差であるBツリー及びB +ツリー:

 

 

 七のハッシュテーブルルックアップ(ハッシュテーブル)★★★★★★★★重要

   (1)に定義されます

      技術をハッシュすると、各キーはメモリ位置F(キー)に対応する格納位置と、そのレコードのキーワード、キーワード間のfは一定の対応関係を確立することです。この対応関係に基づいて、探して、レコードセットを見つけるために、存在する場合、F(キー)キーマップ指定された値を見つけることが判定された場合、その後に位置F(キー)で存在しなければなりません。対応関係は、ハッシュ関数fと呼ばもハッシュ法レコードを使用して、ハッシュ(ハッシュ)関数と呼ばれる連続した記憶空間に格納され、この収納スペースは、連続的にまたはハッシュテーブルハッシュテーブルと呼ばれる(ハッシュ表)。キーワードに対応する記憶場所を記録するハッシュアドレスと呼ばれます。

   (2)の手順を探します

      散列技术既是一种存储方法,也是一种查找方法。散列过程的步骤分为两步: 在存储时,通过散列函数计算记录的散列地址,并按次散列地址存储该记录。 当查找记录时,通过同样的散列函数计算记录的散列地址,按此散列地址访问该记录。

   (3)适合场景

      散列技术与线性表、树、图结构不同的是,散列技术的记录之间不存在什么逻辑关系,它只与关键字有关联。因此,散列主要是面向查找的存储结构。   散列技术最适合的求解问题是查找与给定值相等的记录。不适合同样的关键字对应很多记录或者范围查找。   对于两个不同的关键字key1≠key2,但是却有f(key1)=f(key2),这种现象称为冲突,并把key1和key2称为这个散列函数的同义词。

  (4)散列函数的构造方法

      =》直接定址法 :f(key) = a X key + b(a,b为常数)

      =》数字分析法

      =》平方取中法

      =》折叠法

      =》除留余数法(最常用的散列函数):对于散列表长为m的散列函数公式为:f(key) = key mod p (p ≤m)。

      =》随机数法

  (5)处理散列冲突的方法

  设计得再好的散列函数也不可能完全避免冲突。

  1.开放定址法:fi(key) = (f(key) + di) MOD m(di = 1,2,3...,m-1)

  开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。

  假设关键字集合为{12,67,56,16,25,37,22,29,15,47,48,34},表长为12,f(key) = key MOD 12

  则f(12) = 0,f(67) = 7,f(56) = 8,f(16) = 4,f(25) = 1,而f(37) = 1,则f(37) = (f(37) + 1) MOD 12 = 2,继续f(22) = 10,f(29) = 5,f(15) = 3,f(47) = 11

  而f(48) = 0,冲突,f(48) = (f(48) + 1) MOD 12 = 1,也冲突,f(48) = (f(48) + 1) MOD 12 = 2,还是冲突,一直到f(48) = (f(48) + 6) MOD 12 = 6时才不冲突。

  把这种解决冲突的开放定址法称为线性探测法

  例如48和37这种本来都不是同义词却需要争夺一个地址的情况,称为堆积。堆积使得需要不断处理冲突,无论是存入还是查找效率都会大大降低。

  

  当key=34时,f(key)=10,但是22后面没有空位置了,反而它的前面有一个空位置,尽管可以不断地求余数后得到结果,但效率很差。可以改进di=1²,-1²,2²,-2²,...,q²,-q²(q≤m/2),这样就等于是可以双向寻找到可能的空位置。

  增加平方运算的目的是为了不让关键字都聚集在某一块区域,称这种方法为二次探测法fi(key) = (f(key) + di) MOD m (di=1²,-1²,2²,-2²,...,q²,-q²(q≤m/2))

  还可以对于位移量di采用随机函数计算得到,称之为随机探测法。即设置随机种子相同,每次调用随机函数可以生成不会重复的数列,在查找时,用同样的随机种子,它每次得到的数列是相同的,相同的di可以得到相同的散列地址。fi(key) = (f(key) + di) MOD m(di是一个随机数列)

  2.再散列函数法

  再散列函数法就是事先准备多个散列函数fi(key) = RHi(key) (i=1,2,...,k),每当发生散列地址冲突时,就换一个散列函数计算,这种方法能够使得关键字不产生聚集,也相应增加了计算的时间。  

  3.链地址法

  将所有关键字为同义词的记录存储在一个单链表中,称这种表为同义词子表,在散列表中只存储所有同义词子表的头指针,无论有多少个冲突,都只是在当前位置给单链表增加结点而已。

  例如:0下标→48→12,1下标→37→25...

  链地址法对于可能会造成很多冲突的散列函数来说,提供了绝不会出现找不到地址的保障。当然,也带来了查找时需要遍历单链表的性能损耗。

  4.公共溢出区法

  公共溢出区法就是将所有与之间的关键字位置有冲突的关键字{37,48,34}存入一个公共的溢出区表中。

  在查找时,对给定值通过散列函数计算出散列地址后,先与基本表的相应位置进行对比,如果相等,则查找成功;如果不相等,则到溢出表中进行顺序查找。

  如果相对于基本表而言,有冲突的数据很少的情况下,公共溢出区的结构对查找性能来说还是非常高的。

 

八、Hash例题展示:Hashing

题干

    这道题目只需要用一个数组就可以解决,开始对数组每个元素先初始化为0,然后通过散列映射到数组中去,如果该映射的下标的元素值为0,则把该下标置为我们输入的值,否则就遍历正向的二次探测。这里大家可能会对什么时候才能结束探测循环表示疑问。

    对1来说,他不是素数(质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数),所以对他而言最小素数为2。

    首先需要构造获取素数的函数:

int GetPrime(int x)
{
    if(x == 1)    return 2;
    int p,i;
    if(x % 2 == 1) p = x;
    else p = x + 1;
    while(1) { for(i = sqrt(p); i >= 2; i--) if (p % i == 0) break; if(i == 1) break; else p += 2; } return p; }

    之后就可以开始敲哈希了

    for(int i = 0; i < N; i++)
    {
        if (i != 0) printf(" ");
        scanf("%d", &x);
        pos = x % size;
        tempPos = pos;
        if(A[tempPos] == 0) { A[tempPos] = x; printf("%d", pos); } else { int cnt, flag = 0; for(cnt = 1; cnt < size; cnt++) { pos = (tempPos + cnt*cnt) % size; if(A[pos] == 0) { flag = 1; A[pos] = x; printf("%d", pos); break; } } if(flag == 0) printf("-"); } }

    完整AC答案展示如下:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define MAX 99999999
int size,N,x,pos,tempPos,A[MAX];
int GetPrime(int x)
{
    if(x == 1)    return 2;
    int p,i; if(x % 2 == 1) p = x; else p = x + 1; while(1) { for(i = sqrt(p); i >= 2; i--) if (p % i == 0) break; if(i == 1) break; else p += 2; } return p; } int main() { scanf("%d %d", &size, &N); size = GetPrime(size); for(int i = 0; i < size; i++)//初始化 A[i] = 0; for(int i = 0; i < N; i++) { if (i != 0) printf(" "); scanf("%d", &x); pos = x % size; tempPos = pos; if(A[tempPos] == 0) { A[tempPos] = x; printf("%d", pos); } else { int cnt, flag = 0; for(cnt = 1; cnt < size; cnt++) { pos = (tempPos + cnt*cnt) % size; if(A[pos] == 0) { flag = 1; A[pos] = x; printf("%d", pos); break; } } if(flag == 0) printf("-"); } } return 0; }

 

 九、自我总结与反思:

  最近数挖的课程也要接近尾声,6月15日需要完成大作业,差不多大一也要结束了,收收心准备一些结项了。

  (1)完成基础Python知识学习与巩固复习,完成数挖爬虫作业

  (2)继续攻读统计学习,完成数挖算法作业

  (3)准备下周二多模态情景分析的论文presentation

  (4)继续学习ACM算法——序列自动机

  (5)学业复习及相关考试考级准备

おすすめ

転載: www.cnblogs.com/WinniyGD/p/10941439.html