如何在一個有序鏈表中找到目標值有很多種算法,常用的有時間爲O(n)的確定性算法A,時間爲O(√n)的確定性算法B,時間爲O(n)的概率算法C,在這幾種算法中,算法B效率最高,爲進一步提高算法效率,寫一Sherwood算法C,與算法A, B, D比較,給出實驗結果。
首先定義了一個普通的有序鏈表,再定義一個特殊的有序鏈表,通過A、B、C、D四種算法在兩個鏈表上的不同表現,得出結論。
程序源代碼(C語言描述):
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> #define targ 18 int n=20,head=3,head1=0;//定義靜態鏈表 int val[20]={2,17,11,1,7,15,20,3,19,14,8,5,18,10,13,6,4,12,16,9}; int ptr[20]={7,12,17,0,10,18,100,16,6,5,19,15,8,2,9,4,11,14,1,13}; int val1[20]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}; int ptr1[20]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,100}; void main() { printf("普通有序靜態鏈表0\n"); printf("val[20]={2,17,11,1,7,15,20,3,19,14,8,5,18,10,13,6,4,12,16,9};\n"); printf("ptr[20]={7,12,17,0,10,18,100,16,6,5,19,15,8,2,9,4,11,14,1,13};\n"); printf("-----------------------------------------------------------\n"); printf("特殊有序靜態鏈表1\n"); printf("val1[20]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};\n"); printf("ptr2[20]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,100};\n"); printf("-----------------------------------------------------------\n"); printf("A算法在鏈表0中查找%d:",targ); printf("目標位置i=%d\n",A(targ)); printf("B算法在鏈表0中查找%d:",targ); printf("目標位置i=%d\n",B(targ)); printf("C算法在鏈表0中查找%d:",targ); printf("目標位置i=%d\n",C(targ)); printf("D算法在鏈表0中查找%d:",targ); printf("目標位置i=%d\n",D(targ)); printf("-----------------------------------------------------------\n"); printf("A算法在鏈表1中查找%d:",targ); printf("目標位置i=%d\n",A1(targ)); printf("B算法在鏈表1中查找%d:",targ); printf("目標位置i=%d\n",B1(targ)); printf("C算法在鏈表1中查找%d:",targ); printf("目標位置i=%d\n",C1(targ)); printf("D算法在鏈表1中查找%d:",targ); printf("目標位置i=%d\n",D1(targ)); } int search(int x,int i) {int k=0;//記錄查找的次數 while(x>val[i]) { i=ptr[i]; k++; } printf("共查找了%d次\n",k+1); return i; } int A(int x) //時間爲O(n)的確定性算法 { return search(x,head); } int B(int x) //時間爲O(√n)的確定性算法 { int j,y,i=head; int max=val[i]; //max初值是表val中的最小值 for(j=0;j<sqrt(n);j++) //在val的前√n個數中 //找不大於x的最大整數y相應的下標i { y=val[j]; if(max<y&&y<=x) { i=j; max=y; } } return search(x,i); //從y開始繼續搜索 } int C(int x) //在算法B基礎上改進的sherwood算法 { int j,k,i=head; int max=val[i]; srand( (unsigned)time(0)); for(j=0;j<sqrt(n);j++) {k=rand()%n; //在0-n中取√n個隨機數作爲下標,將這些下標對應的val值 //與x比較,找出不大於x的最大整數相應的下標i if(max<val[k]&&val[k]<=x) {i=k; max=val[k]; } } return search(x,i); } int D(int x) //時間爲O(n)的概率算法 { int i=rand()%n; int y=val[i]; if(x<y) return search(x,head); else if(x>y) return search(x,ptr[i]); else return i; } int search1(int x,int i) {int k=0; while(x>val1[i]) { i=ptr1[i]; k++; } printf("共查找了%d次\n",k+1); return i; } int A1(int x) { return search1(x,head1); } int B1(int x) { int j,y,i=head1; int max=val1[i]; for(j=0;j<sqrt(n);j++) { y=val1[j]; if(max<y&&y<=x) { i=j; max=y; } } return search1(x,i); } int C1(int x) { int j,k,i=head1; int max=val1[i]; srand( (unsigned)time(0)); for(j=0;j<sqrt(n);j++) {k=rand()%n; if(max<val1[k]&&val1[k]<=x) {i=k; max=val1[k]; } } return search1(x,i); } int D1(int x) { int i=rand()%n; int y=val1[i]; if(x<y) return search1(x,head1); else if(x>y) return search1(x,ptr1[i]); else return i; }
運行結果:
可以取不同的targ 多運行幾次。
結論:
1:時間爲O(n)的確定算法A所需時間最長,效率最低
2:時間爲O(n)的概率算法D隨機性很大,對同一target,算法效率有時很高,有時很低。
3、時間爲O(√n)的確定性算法B和在算法B基礎上改進的sherwood算法C在普通有序鏈表中表現較好,旗鼓相當,但當遇到特殊有序表(val[]本身有序)時,算法效率急劇下降。而改進的sherwood算法C卻依舊保持極高的效率。說明sherwood算法雖然並不比同類型確定性算法快,但他消除了最壞實例的影響。