數據結構筆記(查找技術)

  • 查找的基本概念

  • 列表: 有同一類型的數據元素組成的集合

  • 關鍵碼: 數據元素中的某個數據項, 可以標識列表中的一個或一組數據元素

  • 鍵值: 關鍵碼的值

  • 主關鍵碼: 可以唯一標識一個記錄的關鍵碼

  • 次關鍵碼: 不能唯一標識一個記錄的關鍵碼

  • 查找: 在具有相同數據類型的記錄構成的集合中找出滿足給定條件的記錄

  • 查找的結果: 若在查找集合中找到了與給定值相匹配的記錄, 則查找成功; 否則查找失敗

  • 動態查找: 不涉及插入和刪除操作的查找

  • 靜態查找: 涉及插入和刪除操作的查找

  • 查找結構: 面向查找操作的數據結構, 即 基於查找的數據結構

  • 線性表: 適用於靜態查找, 主要採用順序查找技術, 折半查找技術

  • 樹表: 適用於動態查找, 主要採用二叉排序樹的查找技術

  • 散列表: 靜態查找和動態查找均適用, 主要採用散列技術

  • 線性表的查找技術:

  • 順序查找:

  • 基本思想: 從線性表的一端向另一端逐個將關鍵碼與給定值進行比較, 若相等, 則查找成功, 給出該記錄在表中的位置

  • 若整個表檢測完仍未找到與給定值相等的關鍵碼, 則查找失敗, 給出失敗信息

  • 順序查找的優點: 算法簡單而且應用面廣

  • 對錶中記錄的存儲結構及沒有任何要求, 順序存儲和鏈式存儲均可

  • 對錶中記錄的有序性也沒有要求, 無論記錄是否按關鍵碼有序均可

  • 順序查找的缺點: 平均查找長度較大, 特別是當代查找集合元素較多時, 查找效率較低

  • 普通的順序查找方法

  • 帶監視哨的查找技術

  • 折半查找:

  • 適用條件:

  • 線性表中的記錄必須按關鍵碼有序

  • 必須採用順序存儲

  • 基本思想: 在有序表中, 去中間記錄作爲比較對象

  • 若給定的值與中間記錄的關鍵碼相等, 則查找成功

  • 若給定的值小於中間記錄的關鍵碼, 則在中間記錄的左半區繼續查找

  • 若給定的值大於中間記錄的關鍵碼, 則在中間記錄的右半區繼續查找

  • 不斷重複上述過程, 直到查找成功, 或查找的區域無記錄, 則查找失敗

  • 折半查找判定樹

  • 判定樹: 折半查找的過程可以用二叉樹來描述

  • 樹中的每一個結點對應有序表中的一個記錄

  • 結點的值爲該記錄在表中的位置

  • 通常稱這個描述折半查找過程的二叉樹爲折半查找判定樹, 簡稱判定樹

  • 當n=0時,折半查找判定樹爲空;

  • 當n>0時

  • 折半查找判定樹的根結點爲mide(n+1)/2

  • 任意兩棵折半查找判定樹, 若他們的節點個數相同, 則他們的結構完全相同

  • 具有n個結點的折半查找樹的高度爲[log_2~n]+1

  • 任意結點的左右子樹中的結點個數最多相差1

  • 任意結點左右子樹的高度最多相差1

  • 任意兩個葉子結點所處的層數最多相差1

  • 查找成功: 在表中查找任意記錄的過程, 即是折半查找判定樹從根結點到該結點的路徑, 和給定值比較次數等於該記錄結點在樹中的層數

  • #include<iostream>

  • using namespace std;

  • const int MaxSize=100;

  • class LineSearch{

  • public:

  •     LineSearch(int a[],int n);

  •     int SeqSearch(int k);//順序查找

  •     int BinSearch1(int k);//折半查找

  •     int BinSearch2(int k){int high=length;BinSearch2(1,high,k);}

  • private:

  •     int data[MaxSize];

  •     int length;

  •     int BinSearch2(int low,int high,int k);//折半遞歸查找

  • };

  • LineSearch::LineSearch(int a[],int n){

  •     length=n;

  •     for(int i=1;i<=n;i++)

  •         data[i]=a[i];

  • }

  • int LineSearch::SeqSearch(int k){

  •     data[0]=k;

  •     int i=length;

  •     while(data[i]!=k) i--;

  •     return i;

  • }

  • int LineSearch::BinSearch1(int k){

  •     int low=1;

  •     int high=length;

  •     int mide;

  •     while(low<=high){

  •         mide=(low+high)/2;

  •         if(data[mide]>k) high=mide-1;

  •         else if(data[mide]<k) low=mide+1;

  •         else return mide;

  •     }

  •     return 0;

  • }

  • int LineSearch::BinSearch2(int low,int high,int k){

  •     if(low>high) return 0;

  •     else{

  •         int mide=(low+high)/2;

  •         if(data[mide]>k)

  •             return BinSearch2(low,mide-1,k);

  •         else if(data[mide]<k)

  •             return BinSearch2(mide+1,high,k);

  •         else return mide;

  •     }

  • }

  • int main(){

  •     int data[6]={0,3,6,2,7,9};

  •     int data0[6]={0,2,3,6,7,9};

  •     LineSearch li(data0,5);

  •     int n;

  •     while(cin>>n){

  •         int k=li.BinSearch2(n);

  •         if(k==0) cout<<"no answer"<<endl;

  •         else cout<<k<<endl;

  •     }

  • }

  • 二叉排序樹:

  • 或者是一個空的二叉樹, 或者是具有下列性質的二叉樹

  • 若它的左子樹不空, 則左子樹上的所有結點的值均小於根結點的值

  • 若它的右子樹不空, 則右子樹上的所有結點的值均小於根結點的值

  • 它的左右子樹也是二叉排序樹

  • 中序遍歷二叉排序樹可以得到一個按關鍵碼有序的序列

  • 二叉排序樹的插入:

  • 若二叉排序樹爲空樹, 則將新插入的結點爲新的根結點; 否則, 新插入的結點必爲一個新的葉子結點, 其插入位置由查找過程得到

  • 二叉排序樹的刪除算法:

  • 被刪除的是葉子結點: 將雙親結點中相應的指針域的值改爲空

  • 被刪除的結點只有左子樹或者右子樹: 將雙親結點的相應指針域的值 指向被刪除結點的左子樹(或者右子樹)

  • 被刪除的結點既有左子樹也有右子樹: 以其前驅(左子樹中的最大值)代替之, 然後再刪除該結點的前驅結點. 以其後繼(右子樹中的最小值)代替之, 然後再刪除該前驅結點

  • 平衡二叉樹:

  • 或者是一棵空的二叉排序樹, 或者是具有下列性質的二叉排序樹

  • 根結點的左子樹和右子樹的深度最多相差1

  • 根結點的左子樹和右子樹也都是平衡二叉樹

  • 平衡因子: 結點的平衡因子是該結點的左子樹的深度與右子樹的深度之差

  • 最小不平衡子樹: 在平衡二叉樹的構造過程中, 以距離插入結點最近, 且平衡因子絕對值大於1的結點爲根的子樹

  • LL型

  • RR型

  • LR型

  • RL型

  • 散列表:

  • 直接定址法: 適用於事先知道關鍵碼, 關鍵碼集合不是很大且連續性較好

  • 除留餘數法: H(key)=key mod p

  • 一般情況下, 選p爲小於或等於表長(最好接近表長)的最小素數

  • 除留餘數法是一種最簡單, 也是最常用的構造散列函數的方法, 並且不要求事先知道關鍵碼的分佈

  • 數字分析法適用情況於事先知道關鍵碼的分佈, 關鍵碼均勻分佈

  • 平方取中法

  • 摺疊法(分段摺疊法)

  • 衝突處理方法:

  • 開放地址法

  • 鏈地址法

  • 建立公共溢出區

  • 散列表的基本思想: 在記錄的存儲地址和它的關鍵碼之間建立一個確定的對應關係. 這樣不經過比較, 一次就能讀取得到所查元素的查找方法

  • 散列表: 採用散列技術將記錄存儲在一塊連續的存儲空間中, 這塊連續的存儲空間稱爲散列表

  • 散列函數: 將關鍵碼映射爲散列表中適當存儲位置的函數

  • 散列地址: 由散列函數所得的存儲串地址

  • 散列技術既是一種查找技術, 又是一種存儲技術

  • 散列主要是面向查找的存儲結構

  • 散列表一般不適用於允許多個記錄有相同關鍵碼的情況,

  • 有衝突, 降低了查找效率, 體現不出計算式查找的優點

  • 散列法也不適用於範圍查找

  • 不能找到最大值, 最小值

  • 也不可能找到在某一範圍內的記錄

  • 衝突: 對於兩個不同的關鍵碼, 有相同的存儲位置

  • 散列函數設計的原則:

  • 計算簡單

  • 函數值即散列地址分佈均勻

  • 衝突的處理:

  • 開散列方法:拉鍊法, 鏈地址法

  • 閉散列方法: 開放定址法

  • 建立公共溢出區

  • 有關鍵碼得到的散列地址一旦產生了衝突, 就去尋找下一個空的散列地址, 並將記錄存入

  • 線性探測法: 當衝突發生時, 從衝突位置的下一個位置起, 依次尋找空的散列地址

  • 二次探測法

  • 隨機探測法

  • 在falsh法

  • 有開放定址法處理衝突得到的散列表叫閉散列表

  • 裝填因子的作用:

  • 表長=元素個數/ 裝填因子

 

發佈了21 篇原創文章 · 獲贊 4 · 訪問量 2515
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章