美文网首页
从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开始——查找

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