查找的有关操作


1.利用实验一建立有序表,采用折半查找实现某一已知的关键字的查找。

2.随机产生一组关键字,利用二叉排序树的插入算法建立二叉排序树,然后删除某一指定关键字元素。

3.已知散列函数为H(key)=key%p(p为自定的常数),冲突处理方法分别为线性探测法、外拉链法实现
散列表的建立(利用插入算法实现)。 

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
using namespace std;
typedef long long ll;
int a[100];
void erfen(int n,int x)
{
    int l=0,r=n-1,mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(a[mid]==x)
        {
            cout<<x<<"在第"<<mid+1<<"个位置"<<endl;
            return;
        }
        else if(a[mid]>x)
            r=mid-1;
        else l=mid+1;
    }
    cout<<"未能找到"<<x<<endl;
}
struct node
{
    int key;
    node *l,*r;
};
node* InsertBST(node *T,int key)///二叉排序树插入节点
{
    node *f=T,*p=T;
    while(p)
    {
        if(p->key==key) return T;
        f=p;//用f记下查找路径上的最后一个访问的节点
        p=(key<p->key)? p->l:p->r;
    }
    p=(node*)malloc(sizeof(node));
    p->key=key;
    p->l=p->r=NULL;
    if(T==NULL)
        T=p;
    else if (key<f->key)
        f->l=p;
    else
        f->r=p;
    return T;
}
node *CreateBST(int n) ///建立二叉排序树
{
    node *bt=NULL;            //初始时bt为空树
    for(int i=0; i<n; i++)
        bt=InsertBST(bt,a[i]);     //将关键字A[i]插入二叉排序树T中
    return bt;                  //返回建立的二叉排序树的根指针
}

void DelBST(node *T,int key)///二叉排序树删除节点
{
    node *p=T,*f=NULL,*q,*s;
    while(p)
    {
        if(p->key==key) break; //找到关键字为key的结点
        f=p;//记下关键字key节点的父节点
        p=(key<p->key)?p->l:p->r;//分别在*p的左、右子树中查找
    }
    if(!p) return;//二叉排序树中无关键字为key的结点
    if(p->l==NULL&&p->r==NULL) //p没有左右子树
    {
        if(p==T) T=NULL;//删除的是根节点
        else if(p==f->l)
            f->l=NULL;
        else
            f->r=NULL;
        free(p);
    }
    else if(p->l==NULL&&p->r!=NULL)//p无左子树有右子树
    {
        if(f->l==p)
            f->l=p->r; //将p的右子树链接到其父结点的左链上
        else
            f->r=p->r; //将p的右子树链接到其父结点的右链上
        free(p);
    }
    else if(p->r==NULL&&p->l!=NULL)//p有左子树无右子树
    {
        if (f->l==p)
            f->l=p->l; //将p的左子树链接到其父结点的左链上
        else
            f->r=p->l; //将p的左子树链接到其父结点的右链上
        free(p);
    }
    else if(p->l!=NULL&&p->r!=NULL)//p既有左子树又有右子树
    {
        q=p;
        s=p->l;//转左
        while(s->r) //然后向右到尽头
        {
            q=s;
            s=s->r;//s指向被删节点的“前驱”(中序前驱)
        }
        p->key=s->key;//以p的中序前趋结点s代替p(即把s的数据复制到p中)
        if(q!=p) q->r=s->l;//重接q的右子树
        else q->l=s->l;//重接q的左子树。
        free(s);
    }
}

void midorder(node * T )///递归实现中序遍历
{
    if ( T != NULL )
    {
        midorder ( T->l);
        printf("%d ",T->key);
        midorder ( T->r);
    }
}

int tem[100];
vector<int>v[100];
void hash1(int p,int n)///线性探测法
{
    memset(tem,0,sizeof(tem));
    for(int i=0; i<n; i++)
    {
        int tt=a[i]%p;
        if(!tem[tt])
            tem[tt]=a[i];
        else
        {
            for(int j=1; j<=n; j++)
                if(!tem[(tt+j)%n])
                {
                    tem[(tt+j)%n]=a[i];
                    break;
                }
        }
    }
}
void hash2(int p,int n)///外拉链法
{
    for(int i=0; i<n; i++)
        v[a[i]%p].push_back(a[i]);
}


int main()
{
    int n;
    cout<<"请输入n"<<endl;
    cin>>n;
    cout<<"请输入"<<n<<"个有序的数"<<endl;
    for(int i=0; i<n; i++)
        cin>>a[i];
    int x;
    cout<<"请输入要查找的数"<<endl;
    cin>>x;
    erfen(n,x);

    cout<<"请输入n"<<endl;
    cin>>n;
    cout<<"请输入"<<n<<"个数"<<endl;
    for(int i=0; i<n; i++)
        cin>>a[i];
    node *bt;
    bt=CreateBST(n);
    cout<<"中序遍历序列为:"<<endl;
    midorder(bt);
    puts("");
    int num;
    cout<<"请输入要删除的节点"<<endl;
    cin>>num;
    DelBST(bt,num);
    cout<<"删除节点之后中序遍历序列为:"<<endl;
    midorder(bt);
    puts("");

    cout<<"现在建立散列函数为H(key)=key%p,请输入p"<<endl;
    int p;
    cin>>p;
    hash1(p,n);
    cout<<"线性探测法存储"<<n<<"个数的对应位置为"<<endl;
    for(int i=0; i<n; i++)
        cout<<tem[i]<<' ';
    cout<<endl;
    hash2(p,n);
    cout<<"外拉链法存储"<<n<<"个数的对应状态为"<<endl;
    cout<<"余数"<<endl;
    for(int i=0; i<p; i++)
    {
        int l=v[i].size();
        cout<<" "<<i<<"  | ";
        for(int j=0; j<l; j++)
            cout<<v[i][j]<<' ';
        cout<<endl;
    }
    cout<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值