美文网首页
从0开始——查找

从0开始——查找

作者: c枫_撸码的日子 | 来源:发表于2018-11-27 14:07 被阅读0次

一.查找

1.静态查找
要求数据集合是稳定的,不能有添加和删除的查找操作。
2.动态查找
数据集合在查找的过程中需要添加或删除元素的查找操作。

二、查找的实现

1.顺序查找

int sq_serch(int *a,int len,int key)
{
    int i;
    for(i=1;i<=len;i++)//从1开始
    {
        if(a[i] == key)
          return ;
    }
    return 0;
}

1.1.顺序查找的优化

int sq_serch(int *a,int len,int key)
{
    int i=len;//指向末尾
    a[0]=key;//设置一个哨兵
    while(a[i]!=key)
        i--;
    return i;
}

2.折半查找

//二分查找或折半查找
#include <stdio.h>
#include <windows.h> 

int binary_search(int *a,int n,int key)
{
    int low=0,high=n,mid;
    while(low<=high)
    {
        mid = (low + high)/2;//这里写出low+(high-low)/2更好 以防相加溢出

        if(key > a[mid])
            low = mid+1;
        else if(key < a[mid]) 
            high = mid-1;
        else
            return mid;
    }
    return 0;
}
int main()
{
    int a[10] ={1,3,5,8,10,25,66,84,99,106};
    int n=10,key=84;
    int ret=binary_search(a,n,key);
    if(ret==0)
        printf("数据%d在不在数组中");
    else
        printf("数据%d在数组中下标为%d",key,ret);    
    system("pause");
    return 1;
}

3.插值查找

int chazhi_search(int *a,int n,int key)
{
    int low=0,high=n,mid;
    while(low<=high)
    {
        mid = low+(high-low)*(key-a[low])/(a[high]-a[low]);

        if(key > a[mid])
            low = mid+1;
        else if(key < a[mid]) 
            high = mid-1;
        else
            return mid;
    }
    return 0;
}

4.斐波那契查找

int fibonacci_search(int *a,int n,int key)
{
    int low,high,mid,i,k;
        low=0;
        high=n;
        k=0;
        while(n>F(k)-1)//找到n位于斐波那契数列的位置
        {
            k++;
        }
        for(i=0;i<F(k)-1;i++)//补齐不满的数据
            a[i]=a[n];
    while(low<=high)
    {
        mid = low+F[k-1]-1;//取到黄金值的位置

        if(key > a[mid])
        {
            low = mid+1;
            k=k-2;
        }
        else if(key < a[mid]) 
        {
            high = mid-1;
            k=k-1;
        }
        else
        {
           if(mid<=n)
            return mid;
           else
             return n;  
        }
    return 0;
}

5.二叉排序树(二叉查找树)
1.若它的左子树不为空,则左子树上所有节点的值均小于根节点!
2.若它的右子树不为空,则右子树上所有节点的值均小于根节点!
3.它的左右子树也分别为二叉排序树

二叉排序树
//二叉排序树
#include <stdio.h>
#include <windows.h>

//定义二叉排序树节点
typedef struct BNode
{
    int data;//数据 
    struct BNode *left;//左节点 
    struct BNode *right;//右节点 
}BNode,*BTree;//这里的BTree是一个一级指针 

//二叉排序树的查找 
int SearchBST(BTree T,int key,BTree f,BTree *p)
{
    if(T == NULL)
    {
        *p=f;//记录上一个节点 
        return 0;
    }
    else if(key == T->data)//找到了 
    {
        *p = T;
        return 1;
    }
    else if(key > T->data)//key大的话,访问右子树 
    {
        return SearchBST(T->right,key,T,p);     
    }
    else//访问左子树 
        return SearchBST(T->left,key,T,p);
} 
//二叉树的插入
int InsertBTS(BTree *T,int key)
{
    BTree p,s;
    if(!SearchBST(*T,key,NULL,&p))//如果找不到该节点
    {
        s= (BTree)malloc(sizeof(BNode));//创建新节点 
        s->data = key;
        s->left = s->right = NULL;
        
        if(p==NULL)//如果找不到 
        {
            *T=s;//当前节点作为根节点 
        }
        else if(key < p->data)
        {
            p->left=s;  
        }
        else
        {
            p->right = s;       
        }
        return 1;
    } 
    else
    {
        //节点已经存在 就不重复插入 
        return 0;
    }
} 

//二叉排序树的中序遍历
void InOrder(BTree T)
{
    if(T== NULL)
        return;
    InOrder(T->left);//访问左子树 
    printf("%d ",T->data);//访问根 
    InOrder(T->right);//访问右子树 
} 

//二叉排序树的删除
int Delete(BTree *p)
{
    BTree q,s;
    if((*p)->right == NULL)//如果右子树为空,只需将左子树接上去 
    {
        q=*p;//记录当前节点
        *p=(*p)->left;
        free(q);            
    }
    else if((*p)->left == NULL)//左子树为空,只需将右子树接上去即可
    {
        q=*p;
        *p=(*p)->right;
        free(q);
    }
    else//左右子树都不为空 
    {
        q=*p;//记录当前节点
        s=(*p)->left;
        while(s->right)
        {
            q=s;
            s=s->right;
        }
        (*p)->data = s->data;//数据替换
        if(q!=*p)
            q->right = s->left;//重新接到q的 右子树 
        else
            q->left = s->left;  //重新接到q的左子树 
    }   
}

int DeleteBST(BTree *T,int key)
{
    if(*T == NULL)//找不到节点
        return 0; 
    else
    {
        if(key == (*T)->data)
        {
            Delete(T);
        }
        else if (key < (*T)->data)//小于->访问左子树 
        {
            return DeleteBST(&(*T)->left,key);
        }
        else//大于->访问右子树 
        {
            return DeleteBST(&(*T)->right,key); 
        }
    }
} 

int main()
{
    int i;
    
    int a[10] = {62,88,58,47,35,73,51,99,37,93}; 
    BTree T =NULL;
    //二叉排序树的创建 
    printf("当前数组a为:\n");
    for(i=0;i<10;i++)
    {
        printf("%d ",a[i]);
        InsertBTS(&T,a[i]);
    } 
    printf("\n二叉排序BTS创建完毕\n");
    printf("二叉排序树的中序遍历为:\n");
    InOrder(T);
    printf("\n");
    DeleteBST(&T,47);
    printf("删除节点47后的二叉排序树:\n");
    InOrder(T);
    system("pause");
    return 1;
}
结果
6.平衡二叉树
代码有点复杂,暂时略过

7.2-3树,2-3-4树,B树,B+树
理解即可
8.哈希表查找(散列表查找)

//散列表查找法
#include <stdio.h>
#include <windows.h>

#define HASHSIZE 12 //哈希表长度 
#define NULLKEY -36688

typedef struct HashTable
{
    int *elem;//动态分配内存 
    int count;//元素长度 
}HashTable;

//初始化散列表 
void InitHashTable(HashTable *H)
{
    int i;
    H->count = HASHSIZE;//
    H->elem = (int*)malloc(sizeof(int)*HASHSIZE);
    for(i=0;i<HASHSIZE;i++)
        H->elem[i] = NULLKEY;
} 
//散列函数:除留余数法 
int Hash(int key)
{
    return key%HASHSIZE;    
} 
//插入函数 
void Insert(HashTable *H,int key)
{
    int addr = Hash(key);//求出散列地址 
    
    while(H->elem[addr] != NULLKEY)//产生冲突
        addr = (addr+1)%HASHSIZE;//开放定指法的线性探测法 
    H->elem[addr] = key; 
    printf("%d 存放的地址为:%d,H.elem[%d]=%d\n",key,addr,addr,H->elem[addr]);
}
//散列表的查找 
int Search(HashTable *H,int key,int *addr)
{
    *addr = Hash(key);
    while(H->elem[*addr]!=key)//找不到 继续往下找 
    {
        *addr = (*addr+1)%HASHSIZE;
        if(H->elem[*addr]==NULLKEY || *addr ==Hash(key))//回到原点 
        {
            printf("%d 不存在\n",key);
            return 0;//key不存在 
        }       
    }
    printf("%d 在散列表中的地址为%x \n",key,*addr);
    return 1;   
}
//打印散列表 
void showTable(HashTable H)
{
    int i=0;
    printf("散列后为[");
    for(;i<HASHSIZE;i++)
        printf("%d ",H.elem[i]);
    printf("]\n");  
}
int main()
{
    HashTable H;
    int i,j;
    int a[]={12,67,56,16,25,37,22,29,15,47,48,34};  
    InitHashTable(&H);
    for(i=0;i<HASHSIZE;i++)
        Insert(&H,a[i]);
    printf("散列前为[");
    for(i=0;i<HASHSIZE;i++)
        printf("%d ",a[i]);
    printf("]\n");
    showTable(H);
    system("pause");
    return 1;
}

运行结果

散列函数

相关文章

  • 从0开始——查找

    一.查找 1.静态查找要求数据集合是稳定的,不能有添加和删除的查找操作。2.动态查找数据集合在查找的过程中需要添加...

  • 总结js数组方法

    位置方法: indexOf(查找值)//默认从索引0开始查找 indexOf(查找值,从哪里开始找(索引)) la...

  • 2021-02-02

    二分查找(折半查找) 二分查找的过程和序列的下标从0开始还是从1开始无关。一般我们从1开始 数据结构重点讲过,这里...

  • Sqlite常用表查询语句

    1、查找一个表返回其中几条记录 其中limit 0,10中,0表示从第0条记录开始,10表示向下10条记录。 2、...

  • 二分查找

    二分查找 也叫折半查找,从有序列表的候选区li[0:n]开始,通过对 待查找的值和候选区中间值的比较,可以使候选区...

  • 从0开始

    不想再碌碌无为继续这么混下去了好嘛

  • 从0开始

    空杯心态,说着容易做着难。 当我们从有了孩子的欣喜若狂,到孩子第一天上幼儿园的充满希望,然后到小学三四年级的开始纠...

  • 从0开始

    当一家公司开始招聘专业安全人员的时候,意味着安全对这家公司已经比较重要了,比如曾发生一些入侵或者信息泄漏等安全事件...

  • 从0开始

    The best time to plant a tree is twenty years ago. The se...

  • 从0开始

    接触简书已经半年多了,最初是在看一些公众号的文章时偶然间看到了简书,这个集读文写文于一身的平台,早早的就下了这个软...

网友评论

      本文标题:从0开始——查找

      本文链接:https://www.haomeiwen.com/subject/lczafqtx.html