搜索有序链表的四种算法,并比较优劣

      如何在一个有序链表中找到目标值有很多种算法,常用的有时间为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算法虽然并不比同类型确定性算法快,但他消除了最坏实例的影响。

原文地址:https://www.cnblogs.com/yuzeren48/p/2736235.html