查找技术

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了查找技术相关的知识,希望对你有一定的参考价值。

查找的基本概念

关键码:可以表示一个记录的某个数据项;若能唯一标识,称为主关键码,否则为次关键码。
查找:在具有相同类型的记录构成的集合中找出给定条件的记录。
静态查找和动态查找的区别:是否涉及到插入和删除操作。
查找算法的性能:通过平均查找长度ASL进行衡量。

查找结构有:

1.线性表

顺序查找、折半查找、折半查找的递归算法实现,通过插入排序使得数组有序(设置哨兵)

对于表中每个记录的查找过程,可以用折半查找的判定树来描述:
1.从根节点到该节点的路径、给定值的比较次数都等于该记录节点在树中的层数。
2.比较次数最多为log2(n)+1

#include <bits/stdc++.h>

using namespace std;
const int N=1e4+5;
int a[N];
class Lin_search

public:
    Lin_search(int a[],int n);          //线性表的初始化
    ~Lin_search()                     //静态数组,析构函数可为空
    int Seq_search(int k);            //顺序查找
    void Insert_sort();
    int Bin_search1(int k);           //折半查找
    int Bin_search2(int l,int r,int k);           //折半的递归写法
    void display()
    
        for(int i=1;i<=length;i++)
            cout<<d[i]<<" ";
        cout<<endl;
    
private:
    int d[N];
    int length;
;

Lin_search::Lin_search(int a[],int n)

    for(int i=1;i<=n;i++)  //添加哨兵写法
        d[i]=a[i];
    length=n;

int Lin_search::Seq_search(int k)

    int i=length;
    d[0]=d[i];      //哨兵,不必判断是否越界
    while(d[i]!=k)
        i--;
    return i;

void Lin_search::Insert_sort()

    for(int i=2;i<=length;i++)
    
        d[0]=d[i];  //设置哨兵
        int j;
        for(j=i-1;d[j]>d[0];j--)
            d[j+1]=d[j];
        d[j+1]=d[0];
    

int Lin_search::Bin_search1(int k)

    int mid,l=1,r=length;
    while(l<r)
    
        mid=l+r>>1;
        if(k<d[mid])
            r=mid-1;
        else if(k>d[mid])
            l=mid+1;
        else
            return mid;
    

int Lin_search::Bin_search2(int l,int r,int k)

    if(l>r)
        return 0;
    else
    
        int mid=(l+r)/2;
        if(d[mid]>k)
            return Bin_search2(l,mid-1,k);
        else if(d[mid]<k)
            return Bin_search2(mid+1,r,k);
        else
            return mid;
    

int main()

/*
测试数据
5
5 4 6 10 8
*/
    int n;cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    Lin_search lin=Lin_search(a,n);
    cout<<"顺序查找给定值10,在线性表中下标:"<<lin.Seq_search(10)<<endl;

    printf("折半查找要求有序表按关键字升序排列,因此我们使用第八章插入排序对表进行排列!\\n");
    lin.Insert_sort();
    lin.display();
    cout<<"折半查找给定值10,在线性表中下标:"<<lin.Bin_search1(10)<<endl;
    cout<<"折半查找(递归形式)给定值10,在线性表中下标:"<<lin.Bin_search2(1,n,10)<<endl;
    return 0;



树表的查找技术

二叉排序树:
1.左右子树都是二叉排序树
2.若左子树不空,则左子树上所有节点的值均小于根节点的值
3.若右子树不空,则右子树上所有节点的值均大于根节点的值

将具体实现的实现方法放到私有成员中的原因:如果从外界访问,是无法指定从根节点开始遍历的,而类内部可以直接使用。
指针指向的地址,重点理解返回指针类型的方法。

二叉树的删除暂时跳过

#include<bits/stdc++.h>

using namespace std;
const int N=1e4+5;
struct Binode

    int data;
    Binode* lc,* rc;
;
class Binode_sort

public:
    Binode_sort(int a[],int n);
    ~Binode_sort() Release(root);
    Binode* insert_bst(int x)
    
        return insert_bst(root,x);
    
    void preorder()
    
        preorder(root);
    
    Binode* search_bst(int x)
    
        search_bst(root,x);
    
private:
    Binode* insert_bst(Binode* bt,int x);
    Binode* search_bst(Binode* bt,int x);
    Binode* root;
    void Release(Binode* bt);
    void preorder(Binode* bt);  //中序遍历,前序和后序同理
;
Binode_sort::Binode_sort(int a[],int n)

    root=NULL;
    for(int i=1;i<=n;i++)
    
        root=insert_bst(root,a[i]); //关键出错点 服了
    

void Binode_sort::Release(Binode* bt)

    if(bt==NULL)
        return;
    else
    
        Release(bt->lc);
        Release(bt->rc);
        delete bt;
    

Binode* Binode_sort::insert_bst(Binode* bt,int x)

    if(bt==NULL)
    
        Binode* s=new   Binode;
        s->data=x;
        s->lc=s->rc=NULL;
        bt=s;
        return bt;
    
    else if (bt->data > x)
        bt->lc=insert_bst(bt->lc, x);
	else
        bt->rc = insert_bst(bt->rc, x);

Binode* Binode_sort::search_bst(Binode* bt,int x)

    if(bt==NULL) return NULL;
    if(bt->data==x)
        return bt;
    else if(bt->data>x)
        return search_bst(bt->lc,x);
    else
        return search_bst(bt->rc,x);

void Binode_sort::preorder(Binode* bt)

    if(bt==NULL)
        return;
    else
    
        preorder(bt->lc);
        cout<<bt->data<<" ";
        preorder(bt->rc);
    

int main()

/* 测试样例
5
4 5 3 1 10
*/
    int n,a[N];cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    Binode_sort bst=Binode_sort(a,n);
    bst.preorder();
    printf("\\n");
    Binode* p=bst.search_bst(5);
    cout<<"查找给定值的地址:"<<p<<"\\t左子树根节点地址:"<<p->rc<<"\\t右子树根节点:"<<p->rc<<endl;
    return 0;


基于散列表的查找技术

散列表:一块连续的存储空间
散列(哈希)函数:将关键码映射为散列表中适当存储位置的函数
冲突:两个不同的记录放到同一个位置
同义词:造成冲突的两个数

开放地址法:

#include <bits/stdc++.h>

using namespace std;
const int N=1e4+4;
class Hash1

public:
    Hash1();
    ~Hash1()
    int ins(int k);
    int del(int k);
    int sear(int k);
private:
    int H(int k);
    int ht[N];
;
Hash1::Hash1()  //初始化 清0

    memset(ht,0,sizeof(ht));

int Hash1::H(int k)     //散列函数

    return k%11;

int Hash1::ins(int k)   //插入给定值

    int g=H(k);
    if(ht[g]!=0)
    
       while(ht[g]!=0)
         g=(g+1)%N;
       ht[g]=k;
    
    else
        ht[g]=k;

int Hash1::sear(int k)  //检索给定值在表中位置

    int i,j=H(k);
    i=j;
    while(ht[i]!=0)
    
        if(ht[i]==k) return i;
        else i=(i+1)%N;
    
    return -1;

int Hash1::del(int k)

    int g=H(k);
    while(ht[g]!=0)
    
        if(ht[g]==k)

            return g;
        else g=(g+1)%N;
    
    return -1;


int main()

    Hash1 h1=Hash1() ;
    h1.ins(2);
    h1.ins(13);
    h1.ins(25);
    cout<<h1.sear(13)<<endl;
    cout<<h1.sear(25)<<endl;
    int tmp=h1.del(25);
    if(tmp!=-1)
        printf("删除成功!在下标%d处。",tmp);
    else
        printf("表中不出在该值。");
    return 0;


拉链法

#include<bits/stdc++.h>

using namespace std;
const int N=1e4+5;
struct Node

    int data;
    Node* nxt;
;
class Hash2

public:
    Hash2();
    ~Hash2();
    int ins(int k);
    int del(int k);
    Node* sear(int k);
private:
    int H(int k);
    Node* ht[N];
;
Hash2::Hash2()

    for(int i=0;i<N;i++)
    
        ht[i]=new Node;  //为node申请空间,书中没写!!
        ht[i]->nxt=NULL;
    

Hash2::~Hash2()

    Node* p=NULL,* q=NULL;
    for(int i=0;i<N;i++)
    
        p=q=ht[i];
        while(p!=NULL)
        
            p=p->nxt;
            delete q;
            q=p;
        
    

int Hash2::H(int k)

    return k%11;

int Hash2::ins(int k)

    Node* p=ht[H(k)],* s=NULL;
    s=new Node;
    s->data=k;
    s->nxt=p->nxt;
    p->nxt=s;
    return 1;

Node* Hash2::sear(int k)

    Node* p=ht[H(k)];
    while(p!=NULL)
        if(p->data==k)
            return p;
        p=p->nxt;
    
    return NULL;

int Hash2::del(int k)

    Node* p=ht[H(k)],* q=NULL;
    while(p!=NULL)
    
        q=p->nxt;
        if(q->data==k)
        
            p->nxt=q->nxt;
            delete q;
            return 1;
        
        p=p->nxt;
    
    return -1;

int main()

    Hash2 h1=Hash2();
    h1.ins(2);
    h1.ins(13);
    h1.ins(24);
    if(h1.sear(13))
        cout<<"查找成功!存储值:"<<h1.sear(13)->data<<endl;
    if(h1.del(以上是关于查找技术的主要内容,如果未能解决你的问题,请参考以下文章

数据结构——二叉查找(排序)树

数据结构和算法-二叉查找树

二叉查找树

JAVA数据结构--二叉查找树

数据结构之树篇2——二叉排序(查找,搜索)树

数据结构——二叉排序(查找搜索)树