第一篇:數據結構查找實驗報告
實驗題9.1 設計一個程序exp9-1.cpp,輸出在順序表{3,6,2,10,1,8,5,7,4,9}中采用順序方法找關鍵字5的過程。程序如下:
//文件名:exp9-1.cpp #include
KeyType key;
//KeyType為關鍵字的數據類型 //其他數據
//定義表中最多記錄個數
InfoType data;
} NodeType;typedef NodeType SeqList[MAXL];
//順序表類型
int SeqSearch(SeqList R,int n,KeyType k)//順序查找算法
{
int i=0;
while(i { } printf(“%d ”,R[i].key);i++; //從表頭往后找 if(i>=n)return-1; else } void main(){ SeqList R;{ } printf(“%d”,R[i].key);return i; } int n=10,i;KeyType k=5;int a[]={3,6,2,10,1,8,5,7,4,9};for(i=0;i //建立順序表 printf(“關鍵字序列:”);for(i=0;i 截圖如下: 實驗題9.2 設計一個程序exp9-2.cpp,輸出在順序表{1,2,3,4,5,6,7,8,9,10}中采用折半查找法查找關鍵字9的過程。 程序如下: //文件名:exp9-2.cpp #include //定義表中最多記錄個數 KeyType key; //KeyType為關鍵字的數據類型 InfoType data; //其他數據 } NodeType;typedef NodeType SeqList[MAXL]; //順序表類型 int BinSearch(SeqList R,int n,KeyType k)//二分查找算法 { int low=0,high=n-1,mid,count=0;while(low<=high) { mid=(low+high)/2;printf(“ 第%d 次 比 較 :在[%d,%d]R[%d]:%dn”,++count,low,high,mid,R[mid].key); if(R[mid].key==k) //查找成功返回 return mid; if(R[mid].key>k) //繼續在R[low..mid-1]中查找 high=mid-1; else low=mid+1; //繼續在R[mid+1..high]中查找 } return-1;} void main(){ SeqList R;KeyType k=9;int a[]={1,2,3,4,5,6,7,8,9,10},i,n=10;for(i=0;i //建立順序表 R[i].key=a[i];printf(“關鍵字序列:”);for(i=0;i 比 較 元 素 中 } else printf(“元素%d的位置是%dn”,k,i);printf(“元素%d不在表中n”,k); 截圖如下: 實驗題9.3 設計一個程序exp9-3.cpp,輸出在順序表{8,14,6,9,10,22,34,18,19,31,40,38,54,66,46,71,78,68,80,85,100,94,88,96,87}中采用分塊查找法查找(每塊的塊長為5,共5塊)關鍵字46的過程。 程序如下: //文件名:exp9-3.cpp #include KeyType key; //KeyType為關鍵字的數據類型 //定義表中最多記錄個數 //定義索引表的最大長度 InfoType data; //其他數據 } NodeType;typedef NodeType SeqList[MAXL];typedef struct { KeyType key;int link; //KeyType為關鍵字的類型 //指向分塊的起始下標 //順序表類型 } IdxType;typedef IdxType IDX[MAXI]; //索引表類型 int IdxSearch(IDX I,int m,SeqList R,int n,KeyType k)//分塊查找算法 { int low=0,high=m-1,mid,i,count1=0,count2=0;int b=n/m; //b為每塊的記錄個數 printf(“二分查找n”);while(low<=high) //在索引表中進行二分查找,找到的位置存放在low中 { mid=(low+high)/2;printf(“ 第%d 次 比 較 :在[%d,%d] 中 比 較 元R[%d]:%dn”,count1+1,low,high,mid,R[mid].key); if(I[mid].key>=k) high=mid-1; else low=mid+1; count1++; //累計在索引表中的比較次數 } if(low //在索引表中查找成功后,再在線性表中進行順序查找 { printf(“比較%d次,在第%d塊中查找元素%dn”,count1,low,k); i=I[low].link; printf(“順序查找:n ”); while(i<=I[low].link+b-1 && R[i].key!=k) { i++;count2++; printf(“%d ”,R[i].key);} //count2累計在順序表對應塊中的比較次數 printf(“n”); printf(“比較%d次,在順序表中查找元素%dn”,count2,k); if(i<=I[low].link+b-1) return i; else return-1;} 素 } return-1;void main(){ } SeqList R;KeyType k=46;IDX I;int a[]={8,14,6,9,10,22,34,18,19,31,40,38,54,66,46,71,78,68,80,85,100,94,88,96,87},i;for(i=0;i<25;i++)R[i].key=a[i]; //建立順序表 I[0].key=14;I[0].link=0;I[1].key=34;I[1].link=4;I[2].key=66;I[2].link=10;I[3].key=85;I[3].link=15;I[4].key=100;I[4].link=20;if((i=IdxSearch(I,5,R,25,k))!=-1)else printf(“元素%d不在表中n”,k);printf(“元素%d的位置是%dn”,k,i);printf(“n”); 截圖如下: 《數據結構》 第八次實驗報告 學生姓名 學生班級 學生學號 指導老師 重慶郵電大學計算機學院 計算機專業實驗中心 一、實驗內容 1)有序表的二分查找 ?建立有序表,然后進行二分查找 2)二叉排序樹的查找 ?建立二叉排序樹,然后查找 二、需求分析 二分查找的基本思想是將n個元素分成大致相等的兩部分,取a[n/2]與x做比較,如果x=a[n/2],則找到x,算法中止;如果xa[n/2],則只要在數組a的右半部搜索x.時間復雜度無非就是while循環的次數!總共有n個元素,漸漸跟下去就是n,n/2,n/4,....n/2^k(接下來操作元素的剩余個數),其中k就是循環的次數 由于你n/2^k取整后>=1 即令n/2^k=1 可得k=log2n,(是以2為底,n的對數)所以時間復雜度可以表示O()=O(logn)下面提供一段二分查找實現的偽代碼: BinarySearch(max,min,des)mid-<(max+min)/2 while(min<=max)mid=(min+max)/2 if mid=des then return mid elseif mid >des then max=mid-1 else min=mid+1 return max 折半查找法也稱為二分查找法,它充分利用了元素間的次序關系,采用分治策略,可在最壞的情況下用O(log n)完成搜索任務。它的基本思想是,將n個元素分成個數大致相同的兩半,取a[n/2]與欲查找的x作比較,如果x=a[n/2]則找到x,算法終止。如 果xa[n/2],則我們只要在數組a的右 半部繼續搜索x。 三、概要設計 1、順序查找,在順序表R[0..n-1]中查找關鍵字為k的記錄,成功時返回找到的記錄位置,失敗時返回-1,具體的算法如下所示: int SeqSearch(SeqList R,int n,KeyType k){ } int i=0;while(i } if(i>=n){ } printf(“%d”,R[i].key);return i;return-1;else printf(“%d”,R[i].key);i++; 2、二分查找,在有序表R[0..n-1]中進行二分查找,成功時返回記錄的位置,失敗時返回-1,具體的算法如下: int BinSearch(SeqList R,int n,KeyType k){ } return-1;} int low=0,high=n-1,mid,count=0;while(low<=high){ mid=(low+high)/2;printf(“第%d次查找:在[ %d ,%d]中找到元素R[%d]:%dn ”,++count,low,high,mid,R[mid].key);if(R[mid].key==k) return mid;high=mid-1;low=mid+1;if(R[mid].key>k)else 四、詳細設計 源代碼: #include static int a[1024],count=0; void Find1(int low,int high,int x){ int mid;if(low<=high){ mid=(low+high)/2;count++;if(a[mid]>x)Find1(low,mid-1,x);else if(a[mid] void Find2(int low,int high,int x){ int mid;if(low<=high){ mid=(low+high)/2;count++;if(a[mid] 五、心得體會 通過這次在實現順序和二分查找算法的過程中,讓我對順序和二分查找算法有了更多的了解。查找根據給定的某個值,在查找表中確定一個其關鍵字等于給定值的數據元素或(記錄)的操作,應用十分廣泛。順序查找是一種最簡單的查找方法。它的基本思路是:從表的一端開始,順序掃描線性表,依次將掃描到的關鍵字和給定值k相比較,若當前掃描到的關鍵字與k相等,則查找成功;若掃描結束后,仍未找到關鍵字等于k的記錄,則查找失敗。二分查找也稱為折半查找要求線性表中的結點必須己按關鍵字值的遞增或遞減順序排列。它首先用要查找的關鍵字k與中間位置的結點的關鍵字相比較,這個中間結點把線性表分成了兩個子表,若比較結果相等則查找完成;若不相等,再根據k與該中間結點關鍵字的比較大小確定下一步查找哪個子表,這樣遞歸進行下去,直到找到滿足條件的結點或者該線性表中沒有這樣的結點。在學習過程中,善于發現,會找到更多的捷徑。 六、附錄 運行結果截圖。 電 子 科 技 大 學 實 驗 報 告 學生姓名:XXX 學 號:20*** 指導教師:劉嶠 實驗地點:信軟機房306 實驗時間:2014/6/20 一、實驗室名稱:軟件實驗室 二、實驗項目名稱:數據結構與算法—排序與查找 三、實驗學時:4 四、實驗原理: 快速排序的基本思想是:通過一躺排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一不部分的所有數據都要小,然后再按次方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。 假設要排序的數組是A[1]……A[N],首先任意選取一個數據(通常選用第一個數據)作為關鍵數據,然后將所有比它的數都放到它前面,所有比它大的數都放到它后面,這個過程稱為一躺快速排序。一躺快速排序的算法是: 1)設置兩個變量I、J,排序開始的時候I:=1,J:=N 2)以第一個數組元素作為關鍵數據,賦值給X,即X:=A[1]; 3)從J開始向前搜索,即(J:=J-1),找到第一個小于X的值,兩者交換; 4)從I開始向后搜索,即(I:=I+1),找到第一個大于X的值,兩者交換; 5)重復第3、4步,直到I=J。 二分法查找(折半查找)的基本思想: (1)確定該區間的中點位置:mid=(low+high)/2 min代表區間中間的結點的位置,low代表區間最左結點位置,high代表區間最右結點位置 (2)將待查a值與結點mid的關鍵字(下面用R[mid].key)比較,若相等,則查找成功,否則確定新的查找區間: A)如果R[mid].key>a,則由表的有序性可知,R[mid].key右側的值都大于a,所以等于a的關鍵字如果存在,必然在R[mid].key左邊的表中,這時high=mid-1; B)如果R[mid].key C)如果R[mid].key=a,則查找成功。 (3)下一次查找針對新的查找區間,重復步驟(1)和(2) (4)在查找過程中,low逐步增加,high逐步減少,如果high 五、實驗目的: 本實驗通過實現快速排序和折半查找算法,使學生理解如何實現快速查找和排序的基本算法思想。通過練習,加強對算法的理解,提高編程能力。 六、實驗內容: (1)實現數據序列的輸入; (2)實現快速排序算法,并對輸入的序列排序后輸出; (3)實現折半查找算法,并在步驟(2)排序后的序列上,進行任意地 查找,并輸出查詢結果。 七、實驗器材(設備、元器件): 八、數據結構及程序 #include #define MAX_LEN 100 void Sort(int *data,int left,int right){ int i,j,temp; i=left; j=right; temp=data[left]; if(left>right) return; while(i!=j){ while(data[j]>=temp&&j>i) j--; if(j>i) data[i++]=data[j]; while(data[i]<=temp&&j>i) i++; if(j>i) data[j--]=data[i]; } data[i]=temp; Sort(data,left,i-1);PC機一臺,裝有C/C++語言集成開發環境。 Sort(data,i+1,right);} int Search(int *data,int start,int end,int key,int num){ int result; int p =(start + end)/ 2; if(data[p] == key&&start<=end){ result = p; num++; if(data[p] > key) result = Search(data, start, p, key,num); else result = Search(data, p + 1, end, key,num); return result; } else if(num==0&&start>end){ result =-1; printf(“n 404 NO FOUNDn”); return result; } else if(num!=0&&start>end){ result=-1; if(num==1) printf(“nFounded number only one”); else printf(“nFounded number more than one”); return result; } else if(result!=-1){ if(data[p] > key) result = Search(data, start, p-1, key, num); else result = Search(data, p + 1, end, key, num); return result; } else { result=-1; return result; } } void loadFile(int *data,char *filename,int n){ int i; FILE *pfile=NULL; pfile=fopen(filename,“r”); if(!pfile){ printf(“Open file failn”); exit(0); } else printf(“Open file success!n”); for(i = 0;i < n;i++) fscanf(pfile , “%d ”,&data[i]);} int main(int argc, const char * argv[]){ int input=1,data[MAX_LEN],num=0,key=1,i,cmd; char filename[100]; printf(“Choose Mode :n 1.Input Mode 2.File Moden”); scanf(“%d”,&cmd); if(cmd==1){ printf(“Input data :(Enter 0 to detemine)n”); while(input!=0){ printf(“Enter the %d data :”,num+1); scanf(“%d”,&input); if(input!=0){ data[num]=input; num++; } } } else{ printf(“nInput the address of the file: ”); scanf(“%s”,filename); printf(“nInput the number of elem: ”); scanf(“%d”,&num); loadFile(data,filename,--num); } Sort(data, 0, num); printf(“nSort result: ”); for(i=1;i<=num;i++) printf(“%d ”,data[i]); printf(“nn”); while(key!=0){ printf(“nInput a key to search :(Enter 0 to detemine)”); scanf(“%d”,&key); if(key!=0) Search(data, 0, num, key, 0); } return 0;} 九、程序運行結果: 1.打開程序: 2.嘗試手動輸入模式: 3.搜索已存在數: 4.搜索不存在數: 5.嘗試文件讀入模式并搜索 實驗成功。 十、實驗結論: 使用好的排序與查找算法對于程序的運行效率至關重要,一個好的算法,適合的算法能使計算機對數據的處理事半功倍,而選用錯誤的算法,不但可能事倍功半,還有可能造成不穩定因素。 快速排序的時間復雜度為n(log2n),是排序算法中最為快速的一種,但是不穩定,對基本有序的序列效率較差。 二分查找算法在查找算法中,速度快,效率高,但是要求數據要有序。 十一、總結及心得體會: 當空間充足,對穩定性要求不高的情況,排序算法宜使用快速排序。 快速排序和二分查找配合,可以以較高的效率查找目標元素。 數據結構實驗 實驗一 靜態查找表中的查找 一、實驗目的: 1、理解靜態查找表的概念 2、掌握順序查找和折半查找算法及其實現方法 3、理解順序查找和折半查找的特點,學會分析算法的性能 二、實驗內容: 1、按關鍵字從小到大順序輸入一組記錄構造查找表,并且輸出該查找表; 2、給定一個關鍵字值,對所構造的查找表分別進行順序查找和折半查找,輸出查找的結果以及查找過程中“比較”操作的執行次數。 三、實驗要求: 1、查找表的長度、查找表中的記錄和待查找的關鍵字值要從終端輸入; 2、具體的輸入和輸出格式不限; 3、算法要具有較好的健壯性,對錯誤操作要做適當處理; 4、輸出信息中要標明所采用的查找方法類型。 實驗二 基于二叉排序樹的查找 一、實驗目的: 1、理解動態查找表和二叉排序樹的概念 2、掌握二叉排序樹的構造算法及其實現方法 3、掌握二叉排序樹的查找算法及其實現方法 二、實驗內容: 1、輸入一組記錄構造一顆二叉排序樹,并且輸出這棵二叉排序樹的中序序列; 2、給定一個關鍵字值,對所構造的二叉排序樹進行查找,并輸出查找的結果。 三、實驗要求: 1、二叉排序樹中的記錄和待查找的關鍵字值要從終端輸入; 2、輸入的記錄格式為(整數,序號),例如(3, 2)表示關鍵字值為3,輸入序號為2的記錄; 3、算法要具有較好的健壯性,對錯誤操作要做適當處理。 四、程序實現: (1)實現順序查找表和折半查找表: #include int key[MAX_LENGTH]; int length;}stable; int seqserch(stable ST,int key,int &count){ int i; for(i=ST.length;i>0;i--) { count++; if(ST.key[i]==key) return i; } return 0;} int binserch(stable ST,int key,int &count){ int low=1,high=ST.length,mid; while(low<=high) { count++; mid=(low+high)/2; if(ST.key[mid]==key) return mid; else if(key high=mid-1; else low=mid+1; } return 0;} main(){ stable ST1; int a,b,k,x,count1=0,count2=0,temp=0; ST1.length=0; printf(“請按從小到大的順序輸入查找表數據:(-1代表結束!)n”); for(a=0;a { scanf(“%d”,&temp); if(temp!=-1) { ST1.key[a]=temp; ST1.length++; } else break; } printf(“輸入數據為:n”); for(b=0;b { printf(“%d ”,ST1.key[b]); } printf(“n請輸入要查找的數據:”); scanf(“%d”,&k); a=seqserch(ST1,k,count1)+1; printf(“n順序查找: 該數據的位置在第:%d個n”,a); printf(“查找次數為:%dnn”,count1-1); a=binserch(ST1,k,count2)+1; printf(“折半查找: 該數據的位置在第:%d個n”,a); printf(“查找次數為:%dn”,count2-1);}(2)二叉排序樹的查找: #include typedef struct node { int data; int key; struct node *left,*right;}bitnode,*bittree; void serchbst(bittree T,bittree *F,bittree *C,int data){ while(T!=NULL) { if(T->data==data) { *C=T; break; } else if(data { *F=T; T=T->left; } else { *F=T; T=T->right; } } return 0;} int insertbst(bittree *T,int key,int data){ bittree F=NULL,C=NULL,s; serchbst(*T,&F,&C,data); if(C!=NULL)return 0; s=(bittree)malloc(sizeof(bitnode)); s->data=data; s->key=key; s->left=s->right=NULL; if(F==NULL)*T=s; else if(data F->left=s; else F->right=s; return 1;} void creatbst(bittree *T){ int key,data;*T=NULL; printf(“請輸入數據以構造二叉排序樹:(數據格式為:m n(-1000,-1000)代表結束)n”); scanf(“%d%d”,&key,&data); while(key!=-1000 || data!=-1000) { insertbst(T,key,data); scanf(“%d%d”,&key,&data); } } void midTraverse(bittree T){ if(T!=NULL) { midTraverse(T->left); printf(“(%d,%d)”,T->key,T->data); midTraverse(T->right); } } main(){ bittree T=NULL,C=NULL,F=NULL; int key,data,temp; creatbst(&T); printf(“此二叉樹的中序序列為:”); midTraverse(T); printf(“n請輸入要查找的關鍵字:”); scanf(“%d”,&data); serchbst(T,&F,&C,data); printf(“此關鍵字的數據為:%dn”,C->key);} 五、實現結果: (1)順序查找和折半查找: (2)二叉樹排序樹查找: 六、實驗之心得體會: (1)在這次實驗中,我基本上掌握了順序查找、折半查找和二叉排序樹查找的基本思想和實現方法,讓我體會到了寫程序時,不僅要考慮是否能夠調試出結果,還要考慮程序實現的效率,這是一個編程人員必須要具備的一項總要的素質。 (2)通過這次實驗,讓我體會到同樣的數據在不同的查詢方法下有著不同的查詢效率,就拿實驗一來說,用順序查找法在12個數據中查找一個關鍵字需要的查找的次數為8次,但是,如果折半查找法卻只要兩次,由此可以看出,我們在查找時不僅要考慮查找的實現,還要考慮查找的效率和查找所用的時間。 (3)用二叉排序樹查找效率也比較高,只要你輸入相應的關鍵字,就可已找到所需要的數據,就我個人看來,用二叉排序樹的效率要比順序查找和折半查找的效率更高,查詢的速度更快。 實驗六 查找 實驗目的: 掌握幾種查找的思想及算法 問題分析: (一)順序查找 1.查找思想 從表的一端開始逐個將記錄的關鍵字和給定K值進行比較,若某個記錄的關鍵字和給定K值相等,查找成功;否則,若掃描完整個表,仍然沒有找到相應的記錄,則查找失敗。2.算法實現 int Seq_Search(SSTable ST,int key){ int p; } ST.data[0].key=key;/* 設置監視哨兵,失敗返回0 */ for(p=ST.length;ST.data[p].key!=key;p--);return(p); 3.算法分析 設查找每個記錄成功的概率相等,即Pi=1/n;查找第i個元素成功的比較次數Ci=n-i+1 ; ◆ 查找成功時的平均查找長度ASL: ◆ 包含查找不成功時:查找失敗的比較次數為n+1,若成功與不成功的概率相等,對每個記錄的查找概率為Pi=1/(2n),則平均查找長度ASL: (二)折半查找 前提條件:查找表中的所有記錄是按關鍵字有序(升序或降序)。 查找過程中,先確定待查找記錄在表中的范圍,然后逐步縮小范圍(每次將待查記錄所在區間縮小一半),直到找到或找不到記錄為止。1.查找思想 用Low、High和Mid表示待查找區間的下界、上界和中間位置指針,初值為Low=1,High=n。 ⑴ 取中間位置Mid:Mid=?(Low+High)/2? ; ⑵ 比較中間位置記錄的關鍵字與給定的K值: ① 相等: 查找成功; ② 大于:待查記錄在區間的前半段,修改上界指針: High=Mid-1,轉⑴ ; ③ 小于:待查記錄在區間的后半段,修改下界指針:Low=Mid+1,轉⑴ ; 直到越界(Low>High),查找失敗。2.算法實現 int Bin_Search(SSTable ST , KeyType k){ int low=1,high=ST.length, mid; while(low<=high){ mid=(low+high)/2; if(EQ(ST.data[mid].key, k)) return(mid); else if(LT(ST.dat[mid].key, k)) low=mid+1; else high=mid-1; } return(0); /* 查找失敗 */ } 3.算法分析 ① 查找時每經過一次比較,查找范圍就縮小一半,該過程可用一棵二叉樹表示: ◆ 根結點就是第一次進行比較的中間位置的記錄; ◆ 排在中間位置前面的作為左子樹的結點; ◆ 排在中間位置后面的作為右子樹的結點; 對各子樹來說都是相同的。這樣所得到的二叉樹稱為判定樹(Decision Tree)。② 將二叉判定樹的第?㏒2n?+1層上的結點補齊就成為一棵滿二叉樹,深度不變,h= ?㏒2(n+1)?。4.算法分析 ① 查找時每經過一次比較,查找范圍就縮小一半,該過程可用一棵二叉樹表示: ◆ 根結點就是第一次進行比較的中間位置的記錄; ◆ 排在中間位置前面的作為左子樹的結點; ◆ 排在中間位置后面的作為右子樹的結點; 對各子樹來說都是相同的。這樣所得到的二叉樹稱為判定樹(Decision Tree)。② 將二叉判定樹的第?㏒2n?+1層上的結點補齊就成為一棵滿二叉樹,深度不變,h= ?㏒2(n+1)?。 ③ 由滿二叉樹性質知,第i 層上的結點數為2i-1(i≤h),設表中每個記錄的查找概率相等,即Pi=1/n,查找成功時的平均查找長度ASL: 當n很大(n>50)時,ASL≈ ㏒2(n+1)-1。 (三)BST樹 1.BST樹的插入(1)插入思想 在BST樹中插入一個新結點x時,若BST樹為空,則令新結點x為插入后BST樹的根結點;否則,將結點x的關鍵字與根結點T的關鍵字進行比較: ① 若相等: 不需要插入; ② 若x.key 若x.key>T->key:結點x插入到T的右子樹中。(2)算法實現 遞歸算法 void Insert_BST(BSTree T , KeyType key){ BSTNode *s;s=(BSTNode *)malloc(sizeof(BSTNode));s->key=key;s->Lchild=s->Rchild=NULL;if(T==NULL)T=s;else { if(EQ(T->key, s->key))return;/* 已有結點 */ else if(LT(s->key, T->key))Insert_BST(T->Lchild, key);else Insert_BST(T->Rchild, key); } 非遞歸算法 void Insert_BST(BSTree T , KeyType key){ BSTNode *s, *p , *f;s=(BSTNode *)malloc(sizeof(BSTNode));s->key=key;s->Lchild=s->Rchild=NULL;if(T==NULL)T=s;else { p=T; while(p!=NULL) { if(EQ(p->key, s->key))return; f=p; /*q作為p的父結點 */ if(LT(s->key, p->key))p=p->Lchild; else p=p->Rchild; } if(LT(s->key, f->key))f->Lchild=s;else f->Rchild=s;} } 利用BST樹的插入操作,可以從空樹開始逐個插入每個結點,從而建立一棵BST樹,算法如下: #define ENDKEY 65535 BSTree create_BST(){ KeyType key;BSTree T=NULL;scanf(“%d”, &key);while(key!=ENDKEY){ Insert_BST(T, key);scanf(“%d”, &key);} return(T);} 2.BST樹的查找 (1)查找思想 首先將給定的K值與二叉排序樹的根結點的關鍵字進行比較:若相等: 則查找成功; ① 給定的K值小于BST的根結點的關鍵字:繼續在該結點的左子樹上進行查找; ② 給定的K值大于BST的根結點的關鍵字:繼續在該結點的右子樹上進行查找。(2)算法實現 遞歸算法 BSTNode *BST_Serach(BSTree T , KeyType key) { if(T==NULL)return(NULL);else { if(EQ(T->key, key))return(T);else if(LT(key, T->key)) return(BST_Serach(T->Lchild, key)); else return(BST_Serach(T->Rchild, key));} } 非遞歸算法 BSTNode *BST_Serach(BSTree T , KeyType key){ BSTNode * p=T;while(p!=NULL&&!EQ(p->key, key)){ if(LT(key, p->key))p=p->Lchild;else p=p->Rchild;} if(EQ(p->key, key))return(p);else return(NULL);} 在隨機情況下,二叉排序樹的平均查找長度ASL和㏒(n)(樹的深度)是等數量級的。3.BST樹的刪除 (1) 刪除操作過程分析 從BST樹上刪除一個結點,仍然要保證刪除后滿足BST的性質。設被刪除結點為p,其父結點為f,刪除情況如下: ① 若p是葉子結點: 直接刪除p ② 若p只有一棵子樹(左子樹或右子樹):直接用p的左子樹(或右子樹)取代p的位置而成為f的一棵子樹。即原來p是f 的左子樹,則p的子樹成為f 的左子樹;原來p是f 的右子樹,則p的子樹成為f的右子樹 ③ 若p既有左子樹又有右子樹 :處理方法有以下兩種,可以任選其中一種。◆ 用p的直接前驅結點代替p。即從p的左子樹中選擇值最大的結點s放在p的位置(用結點s的內容替換結點p內容),然后刪除結點s。s是p的左子樹中的最右邊的結點且沒有右子樹,對s的刪除同② ◆ 用p的直接后繼結點代替p。即從p的右子樹中選擇值最小的結點s放在p的位置(用結點s的內容替換結點p內容),然后刪除結點s。s是p的右子樹中的最左邊的結點且沒有左子樹,對s的刪除同②(2)算法實現 void Delete_BST(BSTree T , KeyType key) // 在以T為根結點的BST樹中刪除關鍵字為key的結點 { BSTNode *p=T , *f=NULL , *q , *s;while(p!=NULL&&!EQ(p->key, key)){ f=p;//f 指向p的父結點 if(LT(key, p->key))p=p->Lchild;//搜索左子樹 else p=p->Rchild;// 搜索右子樹 } if(p==NULL)return; // 沒有要刪除的結點 s=p; // 找到了要刪除的結點為p if(p->Lchild!=NULL&& p->Rchild!=NULL) { f=p;s=p->Lchild; // 從左子樹開始找 while(s->Rchild!=NULL) { f=s;s=s->Rchild; } // 左、右子樹都不空,找左子樹中最右邊的結點 p->key=s->key;p->otherinfo=s->otherinfo; // 用結點s的內容替換結點p內容 } // 將第3種情況轉換為第2種情況 if(s->Lchild!=NULL) // 若s有左子樹,右子樹為空 q=s->Lchild;else q=s->Rchild;if(f==NULL)T=q;else if(f->Lchild==s)f->Lchild=q; else f->Rchild=q;free(s);} (四)哈希查找 1.基本思想:在記錄的存儲地址和它的關鍵字之間建立一個確定的對應關系;這樣,不經過比較,一次存取就能得到所查元素的查找方法。2.哈希函數 除留余數法 取關鍵字被某個不大于哈希表表長m的數p除后所得余數作哈希地址,即H(key)=key MOD p (p?m)3.沖突處理 ★鏈地址法(拉鏈法) 方法:將所有關鍵字為同義詞(散列地址相同)的記錄存儲在一個單鏈表中,并用一維數組存放鏈表的頭指針。 設散列表長為m,定義一個一維指針數組: RecNode *linkhash[m],其中RecNode是結點類型,每個分量的初值為空。凡散列地址為k的記錄都插入到以linkhash[k]為頭指針的鏈表中,插入位置可以在表頭或表尾或按關鍵字排序插入。(1)鏈地址法查找 int Hash_Insert2(HTNode *T[ ], HTNode *s, int m) { HTNode *p=Hash_Search(T,s->key,m); if(p!=NULL) return 0; //表中已有該結點 else { d=h(s->key); s->next=T[d]; T[d]=s; return 1; //插入成功 } } (2)鏈地址法插入 typedef struct node { KeyType key;struct node *next;}HTNode; HTNode *hash_search2(HTNode *T[ ], KeyType k){ HTNode *p; int i;p=T[h(k)];while(p!=NULL&&p->key!=k) p=p->next;return p;} /*用鏈地址法解決沖突 */ 源程序清單: #include int key;char info;}RecType;#define MAX_SIZE 100 typedef struct SSTable{ // 順序表結構 RecType data[MAX_SIZE]; int length;}SSTable; typedef struct Node{ //二叉樹結構 int key;char info;struct Node *Lchild,*Rchild;}BSTNode; typedef BSTNode * BSTree; int Seq_Search(SSTable ST,int key){ //順序查找 int p; ST.data[0].key=key;for(p=ST.length;ST.data[p].key!=key;p--);return(p);} void Bin_Search(SSTable ST,int key){ //折半查找 int low=1,high=ST.length,mid;int i,j,k; } for(i=1;i if(ST.data[j].key k=j;} if(k!=i){ ST.data[0].key=ST.data[i].key; ST.data[i].key=ST.data[k].key; ST.data[k].key=ST.data[0].key; ST.data[0].info=ST.data[i].info; ST.data[i].info=ST.data[k].info; ST.data[k].info=ST.data[0].info;} } while(low<=high){ mid=(low+high)/2;if(ST.data[mid].key==key)break;else if(ST.data[mid].key //BST樹的插入 BSTNode *s,*p,*f;s=(BSTNode *)malloc(sizeof(BSTNode));s->key=key;s->Lchild=s->Rchild=NULL;s->info=info;if(T==NULL)T=s;else{ p=T; while(p!=NULL){ if(p->key==s->key)break; f=p; if(s->key key)p=p->Lchild; else p=p->Rchild; } if(s->key else f->Rchild=s;} return T;} void InorderTraverse(BSTree T){ if(T!=NULL){ InorderTraverse(T->Lchild); printf(“%d,%ct”,T->key,T->info); InorderTraverse(T->Rchild);} } #define ENDKEY 65535 BSTree create_BST(SSTable ST){ //BST樹的建立 BSTree T=NULL;int i,key,info;for(i=1;i<=ST.length;i++){ key=ST.data[i].key; info=ST.data[i].info; T=Insert_BST(T,key,info);} return T;} BSTNode *BST_Serach(BSTree T,int key){ if(T==NULL)return(NULL);else{ if(T->key==key)return(T); else if(key return(BST_Serach(T->Lchild,key)); else return(BST_Serach(T->Rchild,key));} } BSTree Delete_BST(BSTree T, int key){ //BST樹的刪除 BSTNode *p=T,*f=NULL,*q,*s;while(p!=NULL&&(p->key!=key)){ f=p; if(key key)p=p->Lchild; else p=p->Rchild;} if(p==NULL)return T;else s=p;if(p->Lchild!=NULL&&p->Rchild!=NULL){ f=p;s=p->Lchild; while(s->Rchild!=NULL){ f=s;s=s->Rchild; } p->key=s->key;p->info=s->info;} if(s->Lchild!=NULL)q=s->Lchild;else q=s->Rchild;if(f==NULL)T=q;else if(f->Lchild==s)f->Lchild=q;else f->Rchild=q;free(s);return T;} typedef struct node2{ int key;char info;struct node2 *next;}HTNode;HTNode *Hash_Search(HTNode *T[],int key,int m){ //鏈地址查找 HTNode *p;p=T[key%m];while(p!=NULL&&p->key!=key)p=p->next;return p;} HTNode *Hash_Insert(HTNode *T[],int key,char info,int m){ //鏈地址插入,建立哈希表 HTNode *s=(HTNode *)malloc(sizeof(HTNode));s->key=key;s->info=info;s->next=NULL;HTNode *p=Hash_Search(T,s->key,m);int d;if(p!=NULL)return *T;else{ d=s->key%m; s->next=T[d]; T[d]=s; } return *T;} void main(){ int a,key,p,i,m;char info;SSTable ST;BSTree T=NULL;BSTNode *s;HTNode *HT[20];HTNode *ht;printf(“1.輸入數據n2.順序查找n3.折半查找n4.BST樹的查找n5.BST樹的插入n6.BST樹的刪除n7.鏈地址法查找n8.鏈地址法插入n0.退出n”);while(1){ printf(“n請選擇:”);scanf(“%d”,&a);getchar();switch(a){ case 1: printf(“請輸入記錄數量n:”);scanf(“%d”,&ST.length); printf(“請輸入除數:”);scanf(“%d”,&m); for(i=0;i<20;i++)HT[i]=NULL;for(i=1;i<=ST.length;i++){ printf(“請輸入關鍵字碼與數據:”);scanf(“%d,%c”,&ST.data[i].key,&ST.data[i].info);*HT=Hash_Insert(HT,ST.data[i].key,ST.data[i].info,m);} T=create_BST(ST);printf(“已建立!”);break;case 2:printf(“請輸入要查找的關鍵字碼:”);scanf(“%d”,&key);p=Seq_Search(ST,key);printf(“%d,%cn”,ST.data[p].key,ST.data[p].info);break;case 3:printf(“請輸入要查找的關鍵字碼:”);scanf(“%d”,&key);Bin_Search(ST,key);break;case 4:printf(“請輸入要查找的關鍵字碼:”);scanf(“%d”,&key);s=BST_Serach(T,key);printf(“%d,%cn”,s->key,s->info);break;case 5:printf(“請輸入要添加的關鍵字碼及數據:”);scanf(“%d,%c”,&key,&info);T=Insert_BST(T,key,info);printf(“添加后的結果:”);InorderTraverse(T);printf(“n”); } } break;case 6:printf(“請輸入要刪除的關鍵字碼:”);scanf(“%d”,&key);T=Delete_BST(T,key); printf(“刪除后的結果:”);InorderTraverse(T);printf(“n”);break;case 7:printf(“請輸入要查找的關鍵字碼:”);scanf(“%d”,&key);ht=Hash_Search(HT,key,m);printf(“%d,%cn”,ht->key,ht->info);break;case 8:printf(“請輸入要添加的關鍵字碼及數據:”);scanf(“%d,%c”,&key,&info);*HT=Hash_Insert(HT,key,info,m);for(i=0;i ht=HT[i]; while(ht!=NULL){ printf(“%d,%ct”,ht->key,ht->info); ht=ht->next; } } break;case 0: exit(0);} 運行結果:第二篇:數據結構實驗報告-查找算法
第三篇:數據結構實驗報告-排序與查找
第四篇:數據結構實驗報告-靜態查找表中的查找
第五篇:查找 實驗報告