搜索有序鏈表的四種算法,並比較優劣

      如何在一個有序鏈表中找到目標值有很多種算法,常用的有時間爲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算法雖然並不比同類型確定性算法快,但他消除了最壞實例的影響。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章