1.实验目的(结出本次实验所涉及并要求掌握的知识点)
一、掌握顺序表的查找方法,尤其是二分查找方法。
二、掌握基于链表的查找方法,并能给予实现。
三、掌握二叉排序树的建立以及查找算法,并能给出实现。
2.实验内容(结出实验内容具体描述)
一、利用函数从data1.text读取不同规模数据存入数组,编写基于数组的顺序查找算法。
二、编写基于单链表的顺序查找算法。
三、编写基于数组的非递归二分查找算法
四、编写基于数组的递归二分查找算法
五、以数组中的数据作为输入建立一颗二叉排序树,并将中序遍历。
3.算法描述及实验步骤(用适当的形式表达算法设计思想与算法实现步骤)
一、利用函数从data1.text读取不同规模数据存入数组,编写基于数组的顺序查找算法。
只需要对数组中的每一个元素去进行循环遍历,然后去判断key与元素是否相等。
二、编写基于单链表的顺序查找算法。
只需要对链表中的结点进行遍历,p=p->next;同时去判断p->info是否等于key,如果相等则返回。
三、编写基于数组的非递归二分查找算法
对于非递归我们需要设置一个left,一个right,并且在左指向小于右指向的情况下去进行循环,如果在数组有序的情况下,key的指向小于a[mid]则让right=mid-1再去循环,如果key大于a[mid]则让left=mid+1再循环。如果相等,则返回mid。
四、编写基于数组的递归二分查找算法
同样是设置low high和mid,如果key<a[mid]则运用递归的思想返回binsearch(a,low,mid-1,key),如果是key>a[mid]则返回binsearch(a,mid+1,high,key);如果相等则返回mid。
五、以数组中的数据作为输入建立一颗二叉排序树,并将中序遍历。
首先需要找到插入的位置,这时候我们需要记录一下插入的父节点,这样才能将新创建的结点挂载到父节点下。首先我们进行判断。假若p>key[i]则perent=p,p=p->lchild,我们需要从parent的左子树里去继续循环寻找,直到找到一个位置p为空,这个时候就可以挂载到父节点下了。如果在子树中找到相同的元素,则说明树中已经包含了这个元素,不需要再挂载,我们则用flag标记设置为1,跳出循环。之后我们找到父节点后,根据判断if(flag==0),如果满足条件则创建空间并q->key=a[i],在将这个结点的左右儿子设为空,再根据这个key和parent的key去比较大小。如果小于则挂载到左子树,如果大于则挂载到右子树。
4.调试过程及运行结果(详细记录在调试过程中出现的问题及解决方法。记录实验执行的结果)
一、利用函数从data1.text读取不同规模数据存入数组,编写基于数组的顺序查找算法。
#include "ArrayIo.h"
#define N 10000
int seqsearch(int a[],int n,int key)
{
int i=n-1;
while (i>=0 &&a[i]!=key)
i--;
return i;
}
int main()
{
int a[N],n,x,pos;
n=readData(a,N,"data1.txt");
printf("请输入要查找的整数:");
scanf("%d",&x);
pos=seqsearch(a,n,x);
if (pos==-1)
printf("查找失败");
else
printf("a[%d]=%d\n",pos,x);
}
二、编写基于单链表的顺序查找算法。
#include "slnklist.h"
#define N 10000
linklist seqsearch(linklist head, int key)
{
linklist p=head->next;
while (p && p->info!=key)
p=p->next;
return p;
}
int main()
{
linklist head,pos;
int x;
head= creatLink("data1.txt",N);
/*print(head);*/
printf("请输入要查找的整数:");
scanf("%d",&x);
pos=seqsearch(head,x);
if (pos==NULL)
printf("查找失败!\n");
else
printf("查找成功!%d\n",pos->info);
delList(head);
}
三、编写基于数组的非递归二分查找算法
#include "ArrayIo.h"
#define N 10000
int binSearch(int a[],int n,int key)
{
int left,right,mid;
left=0;
right=n-1;
while (left<=right)
{
mid=(left+right)/2;
if (a[mid]==key)
return mid;
else
if (key<a[mid])
right=mid-1;
else
left=mid+1;
}
return -1;
}
int main()
{
int a[N],n,x,pos;
n=readData(a,N,"data2.txt");
printf("请输入要查找的整数:");
scanf("%d",&x);
pos=binSearch(a,n,x);
if (pos==-1)
printf("查找失败");
else
printf("a[%d]=%d\n",pos,x);
}
四、编写基于数组的递归二分查找算法
#include "ArrayIo.h"
#define N 10000
int binSearch(int a[],int low,int high,int key)
{ int mid;
if (low>high) return -1;
else
{
mid=(low+high)/2;
if (a[mid]==key) return mid;
else
if (key<a[mid])
return binSearch(a,low,mid-1,key);
else
return binSearch(a,mid+1,high,key);
}
}
int main()
{
int a[N],n,x,pos;
n=readData(a,N,"data2.txt");
printf("请输入要查找的整数:");
scanf("%d",&x);
pos=binSearch(a,0,n-1,x);
if (pos==-1)
printf("查找失败");
else
printf("a[%d]=%d\n",pos,x);
}
五、以数组中的数据作为输入建立一颗二叉排序树,并将中序遍历。
#include "Arrayio.h"
#include "bstree.h"
#define N 100
bstree creatBstree(int a[],int n)
{
bstree t=NULL,parent,p,q;
int i,flag;
for (i=0;i<n;i++)
{
parent=NULL;
p=t;
flag=0;
while (p)
{
if (p->key>a[i])
{
parent=p;
p=p->lchild;
}
else if (p->key<a[i])
{
parent=p;
p=p->rchild;
}
else
{
flag=1;
break;
}
}
if (flag==0)
{
q=(bstree)malloc(sizeof(bsnode));
q->key=a[i];
q->lchild=q->rchild=NULL;
if (!t) t=q;
else
if (q->key <parent->key)
parent->lchild=q;
else
parent->rchild=q;
}
}
return t;
}
int main()
{
int n,a[N];
bstree p,t;
n=readData(a,N,"data1.txt");
output(a,n);
t=creatBstree(a,n);
inorder(t);
return 0;
}
5.总结(对实验结果进行分析,问题回答,实验心得体会及改进意见)
本次实验对于链表和顺序表的检索进行了回顾。不论是数组形式进行遍历和判断,还是链表形式进行p=p->next的循环,都是检索的方法,时间复杂度都不少。还有利用递归和非递归的办法去用二分法进行查找,这样虽然对于数组的要求高,要求是有序数组,但是这样时间复杂度会大大降低。还有就是有关二叉排序树的中序遍历,有关于对二叉排序树的创建和插入。
6、一些头文件
bstree.h
#include<stdio.h>
#include<stdlib.h>
typedef struct node1
{
int key;
struct node1 *lchild,*rchild;
}bsnode;
typedef bsnode *bstree;
void inorder(bstree t)
{ if (t) { inorder(t->lchild);
printf("%8d",t->key);
inorder(t->rchild);
}
}
ArrayIo.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 500000
/*从文件中读入数据存入数组a*/
int readData(int a[], int n,char *f ) /*函数返回成功读入的数据个数*/
{
FILE *fp;
int i;
fp=fopen(f,"r");
if (fp==NULL) return 0;
else
{
for (i=0;i<n && !feof(fp);i++)
fscanf(fp,"%d",&a[i]);
fclose(fp);
return i;
}
}
/*存盘函数*/
void saveData(int a[],int n, char *f )
{
FILE *fp;
int i;
fp=fopen(f,"w");
if (fp==NULL) printf("文件建立失败!");
else
{
for (i=0;i<n;i++)
{ if (i%10==0) fprintf(fp,"%c",'\n');
fprintf(fp,"%8d",a[i]);
}
fclose(fp);
}
}
/*输出长度为n的整型数组*/
void output(int a[],int n)
{ int i;
printf("\n数组的内容是:\n");
for (i=0;i<n;i++)
{ if (i%10==0) printf("\n");
printf("%7d",a[i]);
}
printf("\n");
}