第一篇:查找 实验报告
实验六
查找
实验目的:
掌握几种查找的思想及算法 问题分析:
(一)顺序查找 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
(pm)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);} 运行结果: 实验题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)用二叉排序树查找效率也比较高,只要你输入相应的关键字,就可已找到所需要的数据,就我个人看来,用二叉排序树的效率要比顺序查找和折半查找的效率更高,查询的速度更快。第二篇:数据结构查找实验报告
第三篇:数据结构实验报告-查找算法
第四篇:数据结构实验报告-排序与查找
第五篇:数据结构实验报告-静态查找表中的查找