查找算法的研究

1.      顺序查找

顺序查找就是从序列的第一个元素开始,从头到尾逐个查找,直到找到所需的数据或搜索完整个序列。

程序设计如下:

#include <stdio.h>

#pragma hdrstop

#include <tchar.h>

#pragma argsused

int search(int *,int,int);

int _tmain(int argc, _TCHAR* argv[])

{

       inti,a[10],n,x;

       printf("请输入10个数字:\n");

       for(i=0;i<10;i++)

       {

              scanf("%d",a+i);

       }

       printf("\n");

       printf("请输入要查找的数:\n");

       scanf("%d",&x);

       n=search(a,10,x);

       if(n<=0)

       {

              printf("没有找到你想找得数!");

       }

       else

       {

              printf("你想找的数 %d 在数列的第 %d 个位置。",x,n);

       }

       return0;

}

int search(int *a,int num,int value)

{

       intresult=0;

       inti;

       for(i=0;i<num;i++)

       {

              if(value==a[i])

              {

                     result=i+1;

                     break;

              }

       }

       return(result);

}


2.      折半查找

折半查找是将有序数列不断的缩小一半,直到找到该元素或折半区域的首元素位置高于尾元素位置为止。

程序如下:

#include <stdio.h>

#pragma hdrstop

#include <tchar.h>

#pragma argsused

int search(int *,int,int);

int _tmain(int argc, _TCHAR* argv[])

{

       inti,a[10],n,x;

       printf("请输入10个数字:\n");

       for(i=0;i<10;i++)

       {

              scanf("%d",a+i);

       }

       printf("\n");

       printf("请输入要查找的数:\n");

       scanf("%d",&x);

       n=search(a,10,x);

       if(n<=0)

       {

              printf("没有找到你想找得数!");

       }

       else

       {

              printf("你想找的数 %d 在数列的第 %d 个位置。",x,n);

       }

       return0;

}

int search(int *a,int num,int value)

{

       intlow,mid,high;

       low=0;high=num-1;

       while(low<=high)

       {

              mid=(low+high)/2;

              if(a[mid]==value)

              returnmid+1;

              elseif(a[mid]>value)

              high=mid-1;

              else

              low=mid+1;

       }

       return-1;

}


3.      分块查找

分块查找又称为索引顺序查找,是介于顺序查找和二分查找之间的一种查找方法,它是顺序查找的一种方法。

程序设计如下:

#include <stdio.h>

#pragma hdrstop

#include <tchar.h>

#pragma argsused

typedef struct{

int key;

int start;

int end;

}Index;

 

int search(int *,int);

Index index[2];

int _tmain(int argc, _TCHAR* argv[])

{

       inti,a[10],n,x,j=-1;

       printf("请输入10个数字:\n");

       for(i=0;i<10;i++)

       {

              scanf("%d",a+i);

       }

       printf("请输入要查找的数:\n");

       scanf("%d",&x);

       for(i=0;i<2;i++)

       {

              index[i].start=j+1;

              j=j+1;

              index[i].end=j+4;

              j=j+4;

              index[i].key=j;

       }

       n=search(a,x);

       if(n<=0)

       {

              printf("没有找到你想找得数!");

       }

       else

       {

              printf("你想找的数 %d 在数列的第 %d 个位置。",x,n);

       }

       return0;

}

int search(int *a,int value)

{

       inti,j;

       i=0;

       while((i<2)&&(value>a[index[i].key]))

       i++;

       if(i>=2)

       return-1;

       j=index[i].start;

       while(j<=index[i].end&&a[j]!=value)

       j++;

       if(j>index[i].end)

       j=-1;

       returnj;

}

需要注意的是:分块查找中块的大小可根据表的特征进行分块不一定要将线性表分为大小相等的若干块,各块可放在不同的向量中,也可将每一块存放在一个

分块查找的优点:

(1)      在表中插入或删除一个记录中,只要找到该记录所属的块,就在该块内进行插入或删除运算。

(2)      因块内记录的存放是任意的,所以插入和删除比较容易,无需移动大量的记录。

而这种方法的主要代价就是增加了一个辅助数组的内存空间。


4.      哈希查找

哈希查找是通过计算机数据元素的存储地址进行查找的一种方法。其操作步骤为:

(1)      用给定的哈希函数构造哈希表

(2)      根据选择的冲突处理方法解决地址冲突

(3)      在哈希表的基础上执行哈希查找

建立哈希表的步骤:

(1)      取数据元素的关键字key,计算其哈希函数值(地址)。若该地址对应的存储空间还没有被占用,则将该元素存入,否则执行(2)解决冲突。

(2)      根据选择的冲突处理方法,计算关键字key的下一个存储地址,若下一个地址仍被占用,则继续执行步骤(2),直到找到能用的存储地址为止。

设哈希表为[0~m-1],哈希函数取H(key),解决冲突的方法是R(x),则哈希查找的步骤如下:

(1)      给定K值,计算哈希地址Di=H(k);若HST为空,则查找失败,若HST=k,则查找成功。否则执行步骤(2)。

(2)      重复计算处理冲突的下一个存储地址Dk=R(Dk-1),直到HST[Dk]为空,或HST[Dk]=k为止。若HST[Dk]=k,则查找成功,否则查找失败。

在应用哈希查找时,用先设定一个哈希函数和一个冲突处理的方法。

哈希函数的构造有以下几种方法:

(1)      直接定址法

取关键字或者关键字的某个线性函数值为哈希地址。即:

H(key)=key或H(key)=a*key+b;其中,a,b为常数,这种哈希函数叫做自身函数。

(2)      数字分析法

假设关键字是以r为基的数,并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。

(3)      平方取中法

取关键字平方后的中间几位为哈希地址。这是一种较常用的构造哈希函数的方法。通常在选定哈希函数时不一定能知道关键字的全部情况。取其中哪几位也不合适,而一个数平方后的中间几位数和数的每一位都相关,由此使随机分布的关键字得到哈希地址也是随机的,取得位数由表长决定。

(4)      折叠法

将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(含去进位)作为哈希地址,这种方法称为折叠法。关键字位数很多,而且关键字中每一位上数字分布大致均匀时,可以采用折叠法得到哈希地址。

(5)      除留余数法

取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。即:

H(key)=key MOD p, p<=m

这是一种最简单,最常用的构造哈希函数的方法,它不仅可以对关键字直接取模也可以在折叠,平方取中等运算之后取模。

(6)      随机数法

选择一个随机函数,取关键字的随机函数值为哈希地址,即H(key)=random(key)。其中,random为随机函数,通常,当关键字长度不等时采用此法构造呼吸函数较恰当。

处理冲突的方法:

(1)      开放定址法

Hi=(H(key)+di) MOD m i=1,2,3,…,k(k<=m-1)

其中,H(key)为哈希函数,m为哈希表表长,di为增量序列

(2)      再哈希法

RHi均是不同的哈希函数,即在同义词产生地址冲突时计算另一个哈希函数地址,直到冲突不再发生。这种方法不易产生“聚集”,但增加了计算的时间。

(3)      链地址法

将所有关键字为同义词的记录存储在同一线性链表中,假设哈希函数所产生的地址在[0,m-1]上,则设立一个指针型向量。Chain ChainHash[m];其每个分量的初始状态都是空指针。凡哈希地址为i的记录都插入到头指针为ChainHash[i]的链表中。在链表的插入位置可以在表头或表尾,也可以在中间,以保持同义词在同一线性表中按关键字有序。

(4)      建立一个公共溢出区

这是处理冲突的一种方法,假设哈希函数的值域[0,m-1],则设向量HashTable[0..m-1]为基本表,每个分量存放一个记录,另设立向量OverTable[0..v]为溢出表。所有关键字和基本表中关键字为同义词的记录,不管它们由哈希函数得到的哈希地址是什么,一旦发生冲突,都填入溢出表。

 

程序设计如下:

#include <stdio.h>

#include <alloc.h>

#pragma hdrstop

#include <tchar.h>

//---------------------------------------------------------------------------

 

#pragma argsused

#define MAX 5

//定义结点元素

typedef struct

{

       intnum;

       charname[20];

}ElemType;

//定义哈希表

typedef struct

{

       ElemType*elem;

       intcount;

       intsizeindex;

}HashTable;

//定义哈希函数

int Hash(int num)

{

       return(num%5);

}

//创建哈希表

void InitHash(HashTable *H)

{

       inti;

       H->elem=(ElemType*)malloc(MAX*sizeof(ElemType));

       H->count=0;

       H->sizeindex=MAX;

       for(i=0;i<MAX;i++)

       {

              H->elem[i].num=0;

       }

}

//查找函数

int SearchHash(HashTable H,int key, int *p)

{

        int c=0;

        *p=Hash(key);

        while(H.elem[*p].num!=key&&H.elem[*p].num!=0)

        {

              c=c+1;

              if(c%2==1)

              {

                     *p=*p+(c+1)*(c+4)/4;

              }

              else

              {

                     *p=*p-(c*c)/4;

              }

        }

        if(H.elem[*p].num==key)

        {

              return1;

        }

        else

        {

          return 0;

        }

}

//插入函数

void InsertHash(HashTable *H,ElemType e)

{

       intp;

       SearchHash(*H,e.num,&p);

       H->elem[p]=e;

   ++H->count;

}

 

int _tmain(int argc, _TCHAR* argv[])

{

       HashTableH;

       intp,key,i;

       ElemTypee;

       InitHash(&H);

       for(i=0;i<MAX;i++)

       {

loop: printf("输入第 %d 个学生学号\n",i+1);

              scanf("%d",&e.num);

              if(!SearchHash(H,e.num,&p))

              {

                     printf("输入第 %d 个学生姓名\n",i+1);

                     scanf("%s",e.name);

                     InsertHash(&H,e);

              }

              else

              {

                     printf("该学号已经存在\n");

                     gotoloop;

              }

       }

       printf("请输入您要查找的学生学号;\n");

       scanf("%d",&key);

       if(SearchHash(H,key,&p))

       {

              printf("查找成功,学生的姓名是%s\n",H.elem[p].name);

              printf("该学生所在的位置是 %d\n",p);

       }

       else

       {

           printf("查找失败!您要找的学生不存在。");

       }

       return0;

}




<p> 本教程为授权出品 </p> <p> <br /> </p> <p> 课程介绍: </p> <p> <span style="color:#404040;">1.算法是程序的灵魂,优秀的程序在对海量数据处理时,依然保持高速计算,就需要高效的数据结构和算法支撑。</span><br /> <br /> <span style="color:#404040;">2.网上数据结构和算法的课程不少,但存在两个问题:</span><br /> <br /> <span style="color:#404040;">1)授课方式单一,大多是照着代码念一遍,数据结构和算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了</span><br /> <span style="color:#404040;">2)说是讲数据结构和算法,但大多是挂羊头卖狗肉,算法讲的很少。 本课程针对上述问题,有针对性的进行了升级 </span><br /> <span style="color:#404040;">3)授课方式采用图解+算法游戏的方式,让课程生动有趣好理解 </span><br /> <span style="color:#404040;">4)系统全面的讲解了数据结构和算法, 除常用数据结构和算法外,还包括程序员常用10大算法:二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法、马踏棋盘算法。可以解决面试遇到的最短路径、最小生成树、最小连通图、动态规划等问题及衍生出的面试题,让你秒杀其他面试小伙伴</span><br /> <br /> <span style="color:#404040;">3.如果你不想永远都是代码工人,就需要花时间来研究下数据结构和算法。</span><br /> <br /> <span style="color:#404040;">教程内容:</span><br /> <span style="color:#404040;">本教程是使用Java来讲解数据结构和算法,考虑到数据结构和算法较难,授课采用图解加算法游戏的方式。内容包括: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。</span><br /> <br /> <span style="color:#404040;">学习目标:</span><br /> <span style="color:#404040;">通过学习,学员能掌握主流数据结构和算法的实现机制,开阔编程思路,提高优化程序的能力。</span> </p>
相关推荐
©️2020 CSDN 皮肤主题: 程序猿惹谁了 设计师:白松林 返回首页