实验七 查找操作的实现
一、实验学时: 2学时
二、实验目的
- 实现静态查找树的构造方法
- 实现静态查找树的查找方法
三、实验内容
- 折半查找方法的实现
- 二叉排序树的实现
四、主要仪器设备及耗材
- 硬件:计算机一台
- 软件:VC++ 6.0,MSDN2003或者以上版本
五、实验步骤
- 分析问题
- 写出算法
- 编制程序
- 上机调试
- 分析结果
六、程序清单
1.折半查找方法的实现
#include<iostream>
#define MAXSIZE 100
typedef int KeyType; //关键字类型
typedef char InfoType; //数据元素类型
using namespace std;
//数据元素类型定义
typedef struct{
KeyType key; //关键字
InfoType otherinfo; //数据元素
}ElemType;
//定义顺序表结构
typedef struct{
ElemType *R; //存储空间基地址
int length; //顺序表长度
}SSTable;
//初始化顺序表 ,跟第二章的一样
int InitList(SSTable &ST)
{
ST.R=new ElemType[MAXSIZE];
if(!ST.R) exit(-2);
ST.length=0;
return 0;
}
//插入元素
int InsertList(SSTable &ST)
{
KeyType key=0;InfoType data;
cout<<"请输入关键字和数据元素(关键字有序,输入-1退出):\n";
cin>>key>>data;
ST.length=1;
for(int i=1;key!=-1;i++)
{
ST.R[i].key=key;
ST.R[i].otherinfo=data;
cin>>key>>data;
ST.length++; //不要忘了顺序表长度
}
}
//折半查找
int Search_bin(SSTable ST,KeyType key)
{
int low,high,mid;
low=1;high=ST.length; //置查找区间初值,low为1,high为表长
while(low<=high)
{
mid=(low+high)/2; //mid为low和high的均值,也就是找区间中间位置
if(key==ST.R[mid].key) return mid; //若中间位置为所找关键字则返回
else if(key<ST.R[mid].key) high=mid-1; //关键字小于中间的关键字则表明所找关键字在左半区间,将中间关键字-1赋给high
else low=mid+1; //关键字大于中间关键字,则所找关键字在右半区间,将中间关键字+1赋给low
}
return 0; //没找到,返回0
}
int main()
{
SSTable ST; //来个表
InitList(ST); //初始化一下
InsertList(ST); //给点值
cout<<"顺序表构建完成!"<<endl; //建完了,查吧
cout<<"请输入你要查找的数据元素的关键字:";
int search_key;
cin>>search_key;
int locate=Search_bin(ST,search_key); //折半查找
if(locate==0)
{
cout<<"所找关键字不存在!";
return 0;
}
cout<<"关键字为"<<search_key<<"的数据元素是:"<<ST.R[locate].otherinfo<<",它在表中的第"<<locate<<"个位置";
return 0;
}
2.二叉排序树的实现
#include<iostream>
#define ENDFLAG -1 //自定义常量做建树结束标志
using namespace std;
typedef int KeyType;
typedef char InfoType;
//二叉排序树的二叉链表存储表示
typedef struct
{
KeyType key; //关键字项
InfoType otherinfo; //其他数据项
}ElemType; //每个结点的数据域的类型
typedef struct BSTNode
{
ElemType data; //每个结点的数据域包括关键字项和其他数据项
struct BSTNode *lchild,*rchild; //左右孩子指针
}BSTNode,*BSTree;
//二叉排序树的插入
int InsertBST(BSTree &T,ElemType e)
{
//当二叉排序树T中不存在关键字等于e.key的数据元素时,则插入该元素
if(!T)
{ //找到插入位置,递归结束
BSTNode *S;
S=new BSTNode; //生成新结点*S
S->data=e; //新结点*S的数据域置为e
S->lchild=S->rchild=NULL; //新结点*S作为叶子结点
T=S; //把新结点*S链接到已找到的插入位置
}
else if(e.key<T->data.key) //若是要插入的key小于结点的key
InsertBST(T->lchild,e); //递归将e插入它左孩子
else if(e.key>T->data.key) //若是要插入的key大于结点的key
InsertBST(T->rchild,e); //递归将e插入它右孩子
}
//二叉排序树的创建
void CreateBST(BSTree &T)
{
//依次读入一个关键字为key的结点,将此结点插入二叉排序树T中
ElemType e;
T=NULL; //将二叉排序树T初始化为空树
cout<<"请输入key值和数据元素值:";
cin>>e.key>>e.otherinfo;
while(e.key!=ENDFLAG) //ENDFLAG为自定义常量,作为输入结束的标志
{
InsertBST(T,e); //将此结点插入二叉排序树T中
cout<<"请输入key值和数据元素值:";
cin>>e.key>>e.otherinfo;
}
cout<<"二叉排序树创建完毕!"<<endl;
}
//二叉排序树的递归查找
BSTree SearchBST(BSTree T,KeyType key)
{
//在根指针T所指二叉排序树中递归查找某关键字等于key的数据元素
//若查找成功,则返回指向该数据元素结点的指针,否则返回空指针
BSTNode *S;
if((!T)||key==T->data.key) return T; //树为空或查找成功返回T
else if(key<T->data.key) return SearchBST(S->lchild,key); //在左子树中继续查找
else return SearchBST(T->rchild,key); //在右子树中继续查找
}
//二叉排序树的删除
void DeleteBST(BSTree &T,KeyType key)
{
//从二叉排序树T中删除关键字等于key的结点
BSTNode *p=T,*f=NULL; //初始化
//从根结点开始查找关键字等于key的结点*p
while(p)
{
if(p->data.key==key) p=p->lchild; //找到关键字等于key的结点*p,结束循环
f=p; //*f为*p的双亲结点
if(p->data.key>key) p=p->lchild; //在*p的左子树中继续查找
else p=p->rchild; //在*p的右子树中继续查找
}
if(!p) return;
//考虑3种情况实现p所指子树内部的处理:*p左右子树均不空、无右子树、无左子树
BSTNode *q=p;
if((p->lchild)&&(p->rchild)) //被删结点*p左右子树均不空
{
BSTree s=p->lchild;
while(s->rchild) //在*p的左子树中继续查找其前驱结点,即最右下结点
{
q=s;s=s->rchild; //向右直到尽头
}
p->data=s->data; //s指向被删结点的前驱
if(q!=p) q->rchild=s->lchild; //重接*q的右子树
else q->lchild=s->lchild; //重接*q的左子树
delete s;
return;
} //if
else if(!p->rchild) //被删结点*p无右子树,只需重接其左子树
{
p=p->lchild;
} //else if
else if(!p->lchild) //被删结点*p无左子树,只需重接其右子树
{
p=p->rchild;
} //else if
//将p所指的子树挂接到其双亲结点*f相应的位置
if(!f) T=p; //被删结点为根结点
else if(q==f->lchild) f->lchild; //被接到*f的左子树位置
else f->rchild=p; //被接到*f的右子树位置
delete p;
}
int main()
{
BSTree T;
CreateBST(T); //创建树
cout<<"请输入你要查找的key:";
int key;
cin>>key;
BSTree B=SearchBST(T,key); //查找
cout<<"你查找的key值("<<B->data.key<<")对应的数据元素是:"<<B->data.otherinfo;
}
七、运行结果及分析
1.折半查找方法的实现
2.二叉排序树的实现
八、小总结
1.折半查找
折半查找前提是必须是顺序结构必须有序,这个算法是这样的,把第一个关键字位置给low,表长给high,这样就有了这么一个区间,找区间的中间值mid,就是(low+high)/2,如果要找的关键字>mid说明要找的关键字在右半区间,就把mid值给low,再继续折半查找;所找关键字<mid说明所找关键字在左半区间,就把mid值给high,再继续折半。
2.二叉排序的实现
就是来个关键字,从树根往下找,如果大就往右放,如果关键字比树的结点小就往左放。这个要注意在删除操作时有三种情况:左右子树均不空、右子树不空、左子树不空,要删结点左右子树均不空时,把被删结点左子树的最后一个结点(最右侧的结点)放到被删结点的位置(因为左子树最右边是比所删结点小的最大的结点,右边的都比被删结点大不能放),右子树不为空或左子树不为空,直接把被删结点的左孩子或右孩子放到被删结点位置即可。