答主之前写过查找的相应的题目,点击此处查看。我个人感觉之前的价值比较高,对姓名进行查找远比对数字查找重要得多,不过这里主要以平衡二叉树为主,算是对之前的补充了。这里需要说明,个人觉得平衡二叉树构造难度是比较大的,需要多个存储节点进行保存,需要对指针节点相当熟悉后能更加理解深刻,不过这里我会对四种旋转进行代码解释,希望有所帮助。二叉排序树过于简单,这里就直接讲平衡二叉树了。
你的三连就是我创作的最大的动力!
题目描述:
1、创建二叉排序树,实现二叉排序树查找算法。
2、建立有序表,实现折半查找算法。
3、建立哈希表,实现哈希查找算法。
目录
- 平衡二叉树
- 折半查找
- Hash表
平衡二叉树
首先对于四种旋转做个简单的说明。
方法:首先找失衡点,从失衡点开始,经过两步“寻找”,则必然遇到两个结点。加上失衡点,总共三个结点。假设为A、B、C,并规定A<B<C。将这三个结点单独拿出来。把其中的“中位数”B作为根结点,A作为B的左子树,C作为B的右子树,构建一个新的平衡二叉树。并将该新树的根B放到原来的失衡点上。其中,A和C的子树不动。这就是四种旋转的通法。
在代码中,规定Tree->bf正数就是左高,负数就是右高。例如A.bf=2 B.bf=1就是LL旋转了。
对于LL旋转,核心语句:
B=A->lchild;
A->lchild=B->rchild;
//这两步在做什么,简单来说就是将B指向A的左孩,然后再让A左孩指向B的右孩
B->rchild=A;
A->bf=0;B->bf=0;
其余方法类似这里就不多啰嗦了,直接放完整代码。
平衡二叉树代码:
#include <iostream>
#include <cstdlib>
using namespace std;
typedef struct AVLTNode{
int key;
int bf;//平衡因子,正为L,负为R
int num;//输入序号
struct AVLTNode *lchild;
struct AVLTNode *rchild;
}AVLTNode,*AVLTree;
void InsertAVLTree(AVLTree &avlt,int k,int i){
AVLTree S;
AVLTree A,FA,p,fp,B,C;
//将k先插入到新节点S,将k赋给s,同时使s的左右子树为NULL
S=new AVLTNode();
S->key=k;
S->num=i+1;
S->lchild=NULL;
S->rchild=NULL;
S->bf=0;
//如果avlt为NULL,那么s直接插入
if(avlt==NULL){
avlt=S;
}
else{
/* 首先查找S的插入位置fp,同时记录距S的插入位置最近且
平衡因子不等于0(等于-1或1)的结点A,A为可能的失衡结点*/
A=avlt;
FA=NULL;
p=avlt;//p现在为avlt,
fp=NULL;
while(p){
if(p->bf!=0){
A=p;//记录结点可能失衡结点A
FA=fp;
}
//p的因子为0的时候,(因子为0不代表为叶子,意味着左右平衡)将p赋给fp
fp=p;
//当k小于p的key,则遍历p的左树
if(k<p->key) p=p->lchild;
else p=p->rchild;
}
//注意,fp为此时被插入的结点
if(k<fp->key) fp->lchild=S;
else fp->rchild=S;
//A作为失衡结点
//注意,此时插入了结点那么相应的因子数也需要增加,这步比较关键
if(k<A->key){
B=A->lchild;
A->bf++;
}
//注意在此时的定义中,规定bf正数为左高,负数就是为右高,下面就是比较好判断
else {
B=A->rchild;
A->bf--;
}
//此时B就是A的插入节点,将p节点指向B
p=B;
//开始修改节点并且进行旋转,现在已经找到了离插入点最近的失衡节点,开始四种旋转
while(p!=S){
if(k<p->key){
p->bf=1;
p=p->lchild;
}
else{
p->bf=-1;
p=p->rchild;
}
//判断类型进行旋转
//LL型
//这里就将LL,其余相同
if(A->bf==2&&B->bf==1){
//使B结点指向A的左孩
B=A->lchild;
//使A的左孩指向B的右孩
//为什么要这样做说白了就是让A成为B的右孩(前面做的功夫都在存储A的结点信息)
A->lchild=B->rchild;
B->rchild=A;
A->bf=0;
B->bf=0;
if(FA==NULL){
avlt=B;
}
else{
if(A==FA->lchild) FA->lchild=B;
else FA->rchild=B;
}
}
//LR型
else if(A->bf==2&&B->bf==-1){
B=A->lchild;
C=B->rchild;
B->rchild=C->lchild;
A->lchild=C->rchild;
C->lchild=B;
C->rchild=A;
if (S->key < C->key)
{
A->bf=-1;
B->bf=0;
C->bf=0;
}
else
if (S->key >C->key)
{
A->bf=0;
B->bf=1;
C->bf=0;
}
else
{
A->bf=0;
B->bf=0;
}
if (FA==NULL)
avlt=C;
else
if (A==FA->lchild)
FA->lchild=C;
else
FA->rchild=C;
}
//RL型
else if(A->bf==-1&&B->bf==1){
B=A->rchild;
C=B->lchild;
B->lchild=C->rchild;
A->rchild=C->lchild;
C->lchild=A;
C->rchild=B;
if (S->key <C->key) {
A->bf=0;
B->bf=-1;
C->bf=0;
}
else if (S->key >C->key){
A->bf=1;
B->bf=0;
C->bf=0;
}
else {
A->bf=0;
B->bf=0;
}
if (FA==NULL)
avlt=C;
else if (A==FA->lchild)
FA->lchild=C;
else
FA->rchild=C;
}
//RR型
else if (A->bf==-2 && B->bf==-1){
B=A->rchild;
A->rchild=B->lchild;
B->lchild=A;
A->bf=0;
B->bf=0;
if (FA==NULL) avlt=B;
else if (A==FA->lchild)
FA->lchild=B;
else
FA->rchild=B;
}
}
}
}
void CreateAVLT(AVLTree &bst,int a[],int N){
bst=NULL;
for(int i=0;i<N;i++){
InsertAVLTree(bst,a[i],i);
}
}
AVLTree Search(AVLTree bst,int k){
if(!bst) return NULL;
else if(bst->key==k) return bst;
else if(bst->key>k) return Search(bst->lchild,k);
else return Search(bst->rchild,k);
}
int main(){
AVLTree T,temp;
int N;
cout<<"请输入关键字的个数:"<<endl;
cin>>N;
int a[N];
cout<<"请输入关键字序列:"<<endl;
for(int i=0;i<N;i++){
cin>>a[i];
}
CreateAVLT(T,a,N);
cout<<"请输入需要查找的关键字:"<<endl;
int k;
cin>>k;
temp=Search(T,k);
cout<<"关键字的位置在原序列为第"<<temp->num<<"位"<<endl;
return 0;
}
运行结果:
折半查找
#include <iostream>
#include <algorithm>
using namespace std;
typedef struct{
int key;
}Stud;
typedef struct{
Stud a[100];//a[0]为工作单元
int length;
}RecordList;
bool cmp(Stud a,Stud b){
return a.key<b.key;
}
int BinSearch(RecordList l,int k){
int low=1,high=l.length;
int mid;
while(low<=high){
mid=(low+high)/2;
if(l.a[mid].key==k) return mid;
else if(l.a[mid].key>k) high=mid-1;
else low=mid+1;
}
return 0;
}
int main(){
RecordList l;
l.length=0;
int N;
cout<<"请输入关键字的个数:"<<endl;
cin>>N;
cout<<"请输入关键字的序列:"<<endl;
for(int i=1;i<=N;i++){
cin>>l.a[i].key;
l.length++;
}
sort(l.a+1,l.a+N+1,cmp);
cout<<"正序关键字的序列:"<<endl;
for(int i=1;i<=N;i++){
cout<<l.a[i].key<<" ";
}
cout<<"\n请输入需要查找的关键字:"<<endl;
int k;
cin>>k;
int tm=BinSearch(l,k);
if(tm!=0){
cout<<k<<"出现在正序关键字的第"<<tm<<"位"<<endl;
}
else{
cout<<"无此元素"<<endl;
}
return 0;
}
运行结果
Hash表
#include <iostream>
#include <cstdlib>
using namespace std;
const int Hashlength=41;
#define M 37
#define N 30
typedef struct{
int key;
}Stud;
typedef struct{
Stud a[100];//a[0]为工作单元
int length;
}RecordList;
typedef struct{
int key;
int sum;//查找的次数
}HahList;
HahList hasha[Hashlength];
void CreatHash(RecordList l){
int i,count,adr,d;
//初始化hash表
for(i=1;i<Hashlength;i++){
hasha[i].key=0;
hasha[i].sum=0;
}
for(i=1;i<=N;i++){
count=1;
adr=(l.a[i].key)%M;
d=adr;
if(hasha[adr].sum==0){
hasha[adr].key=l.a[i].key;
hasha[adr].sum=1;
}
else{
while(1){
d=(d+(l.a[i].key%10)+1)%M;
count++;
if(hasha[d].sum==0) break;
}
hasha[d].key=l.a[i].key;
hasha[d].sum=count;
}
}
}
void hashFind(int k){
int adr=k%M,d=adr,count=1;
if(hasha[adr].key==k) cout<<k<<"在hash表中是第"<<d<<"位,"<<"查找了"<<count<<"次"<<endl;
else if(hasha[adr].key==0) cout<<"没有此元素"<<endl;
else{
while(1){
d=(d+(k%10)+1)%M;
count++;
if(hasha[d].key==k){
cout<<k<<"在hash表中是第"<<d<<"位,"<<"查找了"<<count<<"次"<<endl;
break;
}
if(hasha[d].key==0){
cout<<"没有此元素"<<endl;
break;
}
}
}
}
int main(){
RecordList l;
cout<<"以下30个元素为随机数:"<<endl;
for(int i=1;i<=30;i++){
int t=rand()%100+1;
cout<<t<<" ";
l.a[i].key=t;
}
CreatHash(l);
cout<<"\n以下为Hash表序列图(注意为0就是该位置为空):"<<endl;
for(int i=1;i<=Hashlength;i++){
cout<<hasha[i].key<<" ";
}
int k;
cout<<"\n请输入需要查找的关键字:"<<endl;
cin>>k;
hashFind(k);
return 0;
}
运行结果,因为hashlength需要长,本次数来自于随机数,并且范围是1-99;